Engine 1.0
Engine Docs
로딩중...
검색중...
일치하는것 없음
json.hpp
이 파일의 문서화 페이지로 가기
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.12.0
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
19#define INCLUDE_NLOHMANN_JSON_HPP_
20
21#include <algorithm> // all_of, find, for_each
22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23#include <functional> // hash, less
24#include <initializer_list> // initializer_list
25#ifndef JSON_NO_IO
26 #include <iosfwd> // istream, ostream
27#endif // JSON_NO_IO
28#include <iterator> // random_access_iterator_tag
29#include <memory> // unique_ptr
30#include <string> // string, stoi, to_string
31#include <utility> // declval, forward, move, pair, swap
32#include <vector> // vector
33
34// #include <nlohmann/adl_serializer.hpp>
35// __ _____ _____ _____
36// __| | __| | | | JSON for Modern C++
37// | | |__ | | | | | | version 3.12.0
38// |_____|_____|_____|_|___| https://github.com/nlohmann/json
39//
40// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
41// SPDX-License-Identifier: MIT
42
43
44
45#include <utility>
46
47// #include <nlohmann/detail/abi_macros.hpp>
48// __ _____ _____ _____
49// __| | __| | | | JSON for Modern C++
50// | | |__ | | | | | | version 3.12.0
51// |_____|_____|_____|_|___| https://github.com/nlohmann/json
52//
53// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
54// SPDX-License-Identifier: MIT
55
56
57
58// This file contains all macro definitions affecting or depending on the ABI
59
60#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
63 #warning "Already included a different version of the library!"
64 #endif
65 #endif
66#endif
67
68#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
69#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum)
70#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
71
72#ifndef JSON_DIAGNOSTICS
73 #define JSON_DIAGNOSTICS 0
74#endif
75
76#ifndef JSON_DIAGNOSTIC_POSITIONS
77 #define JSON_DIAGNOSTIC_POSITIONS 0
78#endif
79
80#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
81 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
82#endif
83
84#if JSON_DIAGNOSTICS
85 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
86#else
87 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
88#endif
89
90#if JSON_DIAGNOSTIC_POSITIONS
91 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
92#else
93 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
94#endif
95
96#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
97 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
98#else
99 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
100#endif
101
102#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
103 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
104#endif
105
106// Construct the namespace ABI tags component
107#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c
108#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
109 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
110
111#define NLOHMANN_JSON_ABI_TAGS \
112 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
113 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
114 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
115 NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
116
117// Construct the namespace version component
118#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
119 _v ## major ## _ ## minor ## _ ## patch
120#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
121 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
122
123#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
124#define NLOHMANN_JSON_NAMESPACE_VERSION
125#else
126#define NLOHMANN_JSON_NAMESPACE_VERSION \
127 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
128 NLOHMANN_JSON_VERSION_MINOR, \
129 NLOHMANN_JSON_VERSION_PATCH)
130#endif
131
132// Combine namespace components
133#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
134#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
135 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
136
137#ifndef NLOHMANN_JSON_NAMESPACE
138#define NLOHMANN_JSON_NAMESPACE \
139 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
140 NLOHMANN_JSON_ABI_TAGS, \
141 NLOHMANN_JSON_NAMESPACE_VERSION)
142#endif
143
144#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
145#define NLOHMANN_JSON_NAMESPACE_BEGIN \
146 namespace nlohmann \
147 { \
148 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
149 NLOHMANN_JSON_ABI_TAGS, \
150 NLOHMANN_JSON_NAMESPACE_VERSION) \
151 {
152#endif
153
154#ifndef NLOHMANN_JSON_NAMESPACE_END
155#define NLOHMANN_JSON_NAMESPACE_END \
156 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
157 } // namespace nlohmann
158#endif
159
160// #include <nlohmann/detail/conversions/from_json.hpp>
161// __ _____ _____ _____
162// __| | __| | | | JSON for Modern C++
163// | | |__ | | | | | | version 3.12.0
164// |_____|_____|_____|_|___| https://github.com/nlohmann/json
165//
166// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
167// SPDX-License-Identifier: MIT
168
169
170
171#include <algorithm> // transform
172#include <array> // array
173#include <forward_list> // forward_list
174#include <iterator> // inserter, front_inserter, end
175#include <map> // map
176#include <string> // string
177#include <tuple> // tuple, make_tuple
178#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
179#include <unordered_map> // unordered_map
180#include <utility> // pair, declval
181#include <valarray> // valarray
182
183// #include <nlohmann/detail/exceptions.hpp>
184// __ _____ _____ _____
185// __| | __| | | | JSON for Modern C++
186// | | |__ | | | | | | version 3.12.0
187// |_____|_____|_____|_|___| https://github.com/nlohmann/json
188//
189// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
190// SPDX-License-Identifier: MIT
191
192
193
194#include <cstddef> // nullptr_t
195#include <exception> // exception
196#if JSON_DIAGNOSTICS
197 #include <numeric> // accumulate
198#endif
199#include <stdexcept> // runtime_error
200#include <string> // to_string
201#include <vector> // vector
202
203// #include <nlohmann/detail/value_t.hpp>
204// __ _____ _____ _____
205// __| | __| | | | JSON for Modern C++
206// | | |__ | | | | | | version 3.12.0
207// |_____|_____|_____|_|___| https://github.com/nlohmann/json
208//
209// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
210// SPDX-License-Identifier: MIT
211
212
213
214#include <array> // array
215#include <cstddef> // size_t
216#include <cstdint> // uint8_t
217#include <string> // string
218
219// #include <nlohmann/detail/macro_scope.hpp>
220// __ _____ _____ _____
221// __| | __| | | | JSON for Modern C++
222// | | |__ | | | | | | version 3.12.0
223// |_____|_____|_____|_|___| https://github.com/nlohmann/json
224//
225// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
226// SPDX-License-Identifier: MIT
227
228
229
230#include <utility> // declval, pair
231// #include <nlohmann/detail/meta/detected.hpp>
232// __ _____ _____ _____
233// __| | __| | | | JSON for Modern C++
234// | | |__ | | | | | | version 3.12.0
235// |_____|_____|_____|_|___| https://github.com/nlohmann/json
236//
237// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
238// SPDX-License-Identifier: MIT
239
240
241
242#include <type_traits>
243
244// #include <nlohmann/detail/meta/void_t.hpp>
245// __ _____ _____ _____
246// __| | __| | | | JSON for Modern C++
247// | | |__ | | | | | | version 3.12.0
248// |_____|_____|_____|_|___| https://github.com/nlohmann/json
249//
250// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
251// SPDX-License-Identifier: MIT
252
253
254
255// #include <nlohmann/detail/abi_macros.hpp>
256
257
259namespace detail
260{
261
262template<typename ...Ts> struct make_void
263{
264 using type = void;
265};
266template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
267
268} // namespace detail
270
271
273namespace detail
274{
275
276// https://en.cppreference.com/w/cpp/experimental/is_detected
278{
279 nonesuch() = delete;
280 ~nonesuch() = delete;
281 nonesuch(nonesuch const&) = delete;
282 nonesuch(nonesuch const&&) = delete;
283 void operator=(nonesuch const&) = delete;
284 void operator=(nonesuch&&) = delete;
285};
286
287template<class Default,
288 class AlwaysVoid,
289 template<class...> class Op,
290 class... Args>
292{
293 using value_t = std::false_type;
294 using type = Default;
295};
296
297template<class Default, template<class...> class Op, class... Args>
298struct detector<Default, void_t<Op<Args...>>, Op, Args...>
299{
300 using value_t = std::true_type;
301 using type = Op<Args...>;
302};
303
304template<template<class...> class Op, class... Args>
305using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
306
307template<template<class...> class Op, class... Args>
308struct is_detected_lazy : is_detected<Op, Args...> { };
309
310template<template<class...> class Op, class... Args>
311using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
312
313template<class Default, template<class...> class Op, class... Args>
314using detected_or = detector<Default, void, Op, Args...>;
315
316template<class Default, template<class...> class Op, class... Args>
317using detected_or_t = typename detected_or<Default, Op, Args...>::type;
318
319template<class Expected, template<class...> class Op, class... Args>
320using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
321
322template<class To, template<class...> class Op, class... Args>
324 std::is_convertible<detected_t<Op, Args...>, To>;
325
326} // namespace detail
328
329// #include <nlohmann/thirdparty/hedley/hedley.hpp>
330
331
332// __ _____ _____ _____
333// __| | __| | | | JSON for Modern C++
334// | | |__ | | | | | | version 3.12.0
335// |_____|_____|_____|_|___| https://github.com/nlohmann/json
336//
337// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
338// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com>
339// SPDX-License-Identifier: MIT
340
341/* Hedley - https://nemequ.github.io/hedley
342 * Created by Evan Nemerson <evan@nemerson.com>
343 */
344
345#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
346#if defined(JSON_HEDLEY_VERSION)
347 #undef JSON_HEDLEY_VERSION
348#endif
349#define JSON_HEDLEY_VERSION 15
350
351#if defined(JSON_HEDLEY_STRINGIFY_EX)
352 #undef JSON_HEDLEY_STRINGIFY_EX
353#endif
354#define JSON_HEDLEY_STRINGIFY_EX(x) #x
355
356#if defined(JSON_HEDLEY_STRINGIFY)
357 #undef JSON_HEDLEY_STRINGIFY
358#endif
359#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
360
361#if defined(JSON_HEDLEY_CONCAT_EX)
362 #undef JSON_HEDLEY_CONCAT_EX
363#endif
364#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
365
366#if defined(JSON_HEDLEY_CONCAT)
367 #undef JSON_HEDLEY_CONCAT
368#endif
369#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
370
371#if defined(JSON_HEDLEY_CONCAT3_EX)
372 #undef JSON_HEDLEY_CONCAT3_EX
373#endif
374#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
375
376#if defined(JSON_HEDLEY_CONCAT3)
377 #undef JSON_HEDLEY_CONCAT3
378#endif
379#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
380
381#if defined(JSON_HEDLEY_VERSION_ENCODE)
382 #undef JSON_HEDLEY_VERSION_ENCODE
383#endif
384#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
385
386#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
387 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
388#endif
389#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
390
391#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
392 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
393#endif
394#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
395
396#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
397 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
398#endif
399#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
400
401#if defined(JSON_HEDLEY_GNUC_VERSION)
402 #undef JSON_HEDLEY_GNUC_VERSION
403#endif
404#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
405 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
406#elif defined(__GNUC__)
407 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
408#endif
409
410#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
411 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
412#endif
413#if defined(JSON_HEDLEY_GNUC_VERSION)
414 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
415#else
416 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
417#endif
418
419#if defined(JSON_HEDLEY_MSVC_VERSION)
420 #undef JSON_HEDLEY_MSVC_VERSION
421#endif
422#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
423 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
424#elif defined(_MSC_FULL_VER) && !defined(__ICL)
425 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
426#elif defined(_MSC_VER) && !defined(__ICL)
427 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
428#endif
429
430#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
431 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
432#endif
433#if !defined(JSON_HEDLEY_MSVC_VERSION)
434 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
435#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
436 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
437#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
438 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
439#else
440 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
441#endif
442
443#if defined(JSON_HEDLEY_INTEL_VERSION)
444 #undef JSON_HEDLEY_INTEL_VERSION
445#endif
446#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
447 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
448#elif defined(__INTEL_COMPILER) && !defined(__ICL)
449 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
450#endif
451
452#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
453 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
454#endif
455#if defined(JSON_HEDLEY_INTEL_VERSION)
456 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
457#else
458 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
459#endif
460
461#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
462 #undef JSON_HEDLEY_INTEL_CL_VERSION
463#endif
464#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
465 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
466#endif
467
468#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
469 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
470#endif
471#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
472 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
473#else
474 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
475#endif
476
477#if defined(JSON_HEDLEY_PGI_VERSION)
478 #undef JSON_HEDLEY_PGI_VERSION
479#endif
480#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
481 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
482#endif
483
484#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
485 #undef JSON_HEDLEY_PGI_VERSION_CHECK
486#endif
487#if defined(JSON_HEDLEY_PGI_VERSION)
488 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
489#else
490 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
491#endif
492
493#if defined(JSON_HEDLEY_SUNPRO_VERSION)
494 #undef JSON_HEDLEY_SUNPRO_VERSION
495#endif
496#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
497 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
498#elif defined(__SUNPRO_C)
499 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
500#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
501 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
502#elif defined(__SUNPRO_CC)
503 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
504#endif
505
506#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
507 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
508#endif
509#if defined(JSON_HEDLEY_SUNPRO_VERSION)
510 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
511#else
512 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
513#endif
514
515#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
516 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
517#endif
518#if defined(__EMSCRIPTEN__)
519 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
520#endif
521
522#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
523 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
524#endif
525#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
526 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
527#else
528 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
529#endif
530
531#if defined(JSON_HEDLEY_ARM_VERSION)
532 #undef JSON_HEDLEY_ARM_VERSION
533#endif
534#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
535 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
536#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
537 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
538#endif
539
540#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
541 #undef JSON_HEDLEY_ARM_VERSION_CHECK
542#endif
543#if defined(JSON_HEDLEY_ARM_VERSION)
544 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
545#else
546 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
547#endif
548
549#if defined(JSON_HEDLEY_IBM_VERSION)
550 #undef JSON_HEDLEY_IBM_VERSION
551#endif
552#if defined(__ibmxl__)
553 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
554#elif defined(__xlC__) && defined(__xlC_ver__)
555 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
556#elif defined(__xlC__)
557 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
558#endif
559
560#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
561 #undef JSON_HEDLEY_IBM_VERSION_CHECK
562#endif
563#if defined(JSON_HEDLEY_IBM_VERSION)
564 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
565#else
566 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
567#endif
568
569#if defined(JSON_HEDLEY_TI_VERSION)
570 #undef JSON_HEDLEY_TI_VERSION
571#endif
572#if \
573 defined(__TI_COMPILER_VERSION__) && \
574 ( \
575 defined(__TMS470__) || defined(__TI_ARM__) || \
576 defined(__MSP430__) || \
577 defined(__TMS320C2000__) \
578 )
579#if (__TI_COMPILER_VERSION__ >= 16000000)
580 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
581#endif
582#endif
583
584#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
585 #undef JSON_HEDLEY_TI_VERSION_CHECK
586#endif
587#if defined(JSON_HEDLEY_TI_VERSION)
588 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
589#else
590 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
591#endif
592
593#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
594 #undef JSON_HEDLEY_TI_CL2000_VERSION
595#endif
596#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
597 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
598#endif
599
600#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
601 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
602#endif
603#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
604 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
605#else
606 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
607#endif
608
609#if defined(JSON_HEDLEY_TI_CL430_VERSION)
610 #undef JSON_HEDLEY_TI_CL430_VERSION
611#endif
612#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
613 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
614#endif
615
616#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
617 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
618#endif
619#if defined(JSON_HEDLEY_TI_CL430_VERSION)
620 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
621#else
622 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
623#endif
624
625#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
626 #undef JSON_HEDLEY_TI_ARMCL_VERSION
627#endif
628#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
629 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
630#endif
631
632#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
633 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
634#endif
635#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
636 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
637#else
638 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
639#endif
640
641#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
642 #undef JSON_HEDLEY_TI_CL6X_VERSION
643#endif
644#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
645 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
646#endif
647
648#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
649 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
650#endif
651#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
652 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
653#else
654 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
655#endif
656
657#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
658 #undef JSON_HEDLEY_TI_CL7X_VERSION
659#endif
660#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
661 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
662#endif
663
664#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
665 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
666#endif
667#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
668 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
669#else
670 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
671#endif
672
673#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
674 #undef JSON_HEDLEY_TI_CLPRU_VERSION
675#endif
676#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
677 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
678#endif
679
680#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
681 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
682#endif
683#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
684 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
685#else
686 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
687#endif
688
689#if defined(JSON_HEDLEY_CRAY_VERSION)
690 #undef JSON_HEDLEY_CRAY_VERSION
691#endif
692#if defined(_CRAYC)
693 #if defined(_RELEASE_PATCHLEVEL)
694 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
695 #else
696 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
697 #endif
698#endif
699
700#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
701 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
702#endif
703#if defined(JSON_HEDLEY_CRAY_VERSION)
704 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
705#else
706 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
707#endif
708
709#if defined(JSON_HEDLEY_IAR_VERSION)
710 #undef JSON_HEDLEY_IAR_VERSION
711#endif
712#if defined(__IAR_SYSTEMS_ICC__)
713 #if __VER__ > 1000
714 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
715 #else
716 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
717 #endif
718#endif
719
720#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
721 #undef JSON_HEDLEY_IAR_VERSION_CHECK
722#endif
723#if defined(JSON_HEDLEY_IAR_VERSION)
724 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
725#else
726 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
727#endif
728
729#if defined(JSON_HEDLEY_TINYC_VERSION)
730 #undef JSON_HEDLEY_TINYC_VERSION
731#endif
732#if defined(__TINYC__)
733 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
734#endif
735
736#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
737 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
738#endif
739#if defined(JSON_HEDLEY_TINYC_VERSION)
740 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
741#else
742 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
743#endif
744
745#if defined(JSON_HEDLEY_DMC_VERSION)
746 #undef JSON_HEDLEY_DMC_VERSION
747#endif
748#if defined(__DMC__)
749 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
750#endif
751
752#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
753 #undef JSON_HEDLEY_DMC_VERSION_CHECK
754#endif
755#if defined(JSON_HEDLEY_DMC_VERSION)
756 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
757#else
758 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
759#endif
760
761#if defined(JSON_HEDLEY_COMPCERT_VERSION)
762 #undef JSON_HEDLEY_COMPCERT_VERSION
763#endif
764#if defined(__COMPCERT_VERSION__)
765 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
766#endif
767
768#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
769 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
770#endif
771#if defined(JSON_HEDLEY_COMPCERT_VERSION)
772 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
773#else
774 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
775#endif
776
777#if defined(JSON_HEDLEY_PELLES_VERSION)
778 #undef JSON_HEDLEY_PELLES_VERSION
779#endif
780#if defined(__POCC__)
781 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
782#endif
783
784#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
785 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
786#endif
787#if defined(JSON_HEDLEY_PELLES_VERSION)
788 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
789#else
790 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
791#endif
792
793#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
794 #undef JSON_HEDLEY_MCST_LCC_VERSION
795#endif
796#if defined(__LCC__) && defined(__LCC_MINOR__)
797 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
798#endif
799
800#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
801 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
802#endif
803#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
804 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
805#else
806 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
807#endif
808
809#if defined(JSON_HEDLEY_GCC_VERSION)
810 #undef JSON_HEDLEY_GCC_VERSION
811#endif
812#if \
813 defined(JSON_HEDLEY_GNUC_VERSION) && \
814 !defined(__clang__) && \
815 !defined(JSON_HEDLEY_INTEL_VERSION) && \
816 !defined(JSON_HEDLEY_PGI_VERSION) && \
817 !defined(JSON_HEDLEY_ARM_VERSION) && \
818 !defined(JSON_HEDLEY_CRAY_VERSION) && \
819 !defined(JSON_HEDLEY_TI_VERSION) && \
820 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
821 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
822 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
823 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
824 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
825 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
826 !defined(__COMPCERT__) && \
827 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
828 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
829#endif
830
831#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
832 #undef JSON_HEDLEY_GCC_VERSION_CHECK
833#endif
834#if defined(JSON_HEDLEY_GCC_VERSION)
835 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
836#else
837 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
838#endif
839
840#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
841 #undef JSON_HEDLEY_HAS_ATTRIBUTE
842#endif
843#if \
844 defined(__has_attribute) && \
845 ( \
846 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
847 )
848# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
849#else
850# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
851#endif
852
853#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
854 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
855#endif
856#if defined(__has_attribute)
857 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
858#else
859 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
860#endif
861
862#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
863 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
864#endif
865#if defined(__has_attribute)
866 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
867#else
868 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
869#endif
870
871#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
872 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
873#endif
874#if \
875 defined(__has_cpp_attribute) && \
876 defined(__cplusplus) && \
877 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
878 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
879#else
880 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
881#endif
882
883#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
884 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
885#endif
886#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
887 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
888#elif \
889 !defined(JSON_HEDLEY_PGI_VERSION) && \
890 !defined(JSON_HEDLEY_IAR_VERSION) && \
891 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
892 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
893 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
894#else
895 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
896#endif
897
898#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
899 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
900#endif
901#if defined(__has_cpp_attribute) && defined(__cplusplus)
902 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
903#else
904 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
905#endif
906
907#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
908 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
909#endif
910#if defined(__has_cpp_attribute) && defined(__cplusplus)
911 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
912#else
913 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
914#endif
915
916#if defined(JSON_HEDLEY_HAS_BUILTIN)
917 #undef JSON_HEDLEY_HAS_BUILTIN
918#endif
919#if defined(__has_builtin)
920 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
921#else
922 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
923#endif
924
925#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
926 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
927#endif
928#if defined(__has_builtin)
929 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
930#else
931 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
932#endif
933
934#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
935 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
936#endif
937#if defined(__has_builtin)
938 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
939#else
940 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
941#endif
942
943#if defined(JSON_HEDLEY_HAS_FEATURE)
944 #undef JSON_HEDLEY_HAS_FEATURE
945#endif
946#if defined(__has_feature)
947 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
948#else
949 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
950#endif
951
952#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
953 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
954#endif
955#if defined(__has_feature)
956 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
957#else
958 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
959#endif
960
961#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
962 #undef JSON_HEDLEY_GCC_HAS_FEATURE
963#endif
964#if defined(__has_feature)
965 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
966#else
967 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
968#endif
969
970#if defined(JSON_HEDLEY_HAS_EXTENSION)
971 #undef JSON_HEDLEY_HAS_EXTENSION
972#endif
973#if defined(__has_extension)
974 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
975#else
976 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
977#endif
978
979#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
980 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
981#endif
982#if defined(__has_extension)
983 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
984#else
985 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
986#endif
987
988#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
989 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
990#endif
991#if defined(__has_extension)
992 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
993#else
994 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
995#endif
996
997#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
998 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
999#endif
1000#if defined(__has_declspec_attribute)
1001 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1002#else
1003 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1004#endif
1005
1006#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1007 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1008#endif
1009#if defined(__has_declspec_attribute)
1010 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1011#else
1012 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1013#endif
1014
1015#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1016 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1017#endif
1018#if defined(__has_declspec_attribute)
1019 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1020#else
1021 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1022#endif
1023
1024#if defined(JSON_HEDLEY_HAS_WARNING)
1025 #undef JSON_HEDLEY_HAS_WARNING
1026#endif
1027#if defined(__has_warning)
1028 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1029#else
1030 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1031#endif
1032
1033#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1034 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1035#endif
1036#if defined(__has_warning)
1037 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1038#else
1039 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1040#endif
1041
1042#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1043 #undef JSON_HEDLEY_GCC_HAS_WARNING
1044#endif
1045#if defined(__has_warning)
1046 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1047#else
1048 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1049#endif
1050
1051#if \
1052 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1053 defined(__clang__) || \
1054 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1055 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1056 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1057 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1058 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1059 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1060 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1061 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1062 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1063 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1064 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1065 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1066 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1067 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1068 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1069 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1070 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1071#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1072 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1073#else
1074 #define JSON_HEDLEY_PRAGMA(value)
1075#endif
1076
1077#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1078 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1079#endif
1080#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1081 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1082#endif
1083#if defined(__clang__)
1084 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1085 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1086#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1087 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1088 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1089#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1090 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1091 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1092#elif \
1093 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1094 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1095 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1096 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1097#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1098 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1099 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1100#elif \
1101 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1102 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1103 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1104 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1105 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1106 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1107 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1108 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1109#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1110 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1111 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1112#else
1113 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1114 #define JSON_HEDLEY_DIAGNOSTIC_POP
1115#endif
1116
1117/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1118 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1119#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1120 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1121#endif
1122#if defined(__cplusplus)
1123# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1124# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1125# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1126# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1127 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1128 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1129 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1130 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1131 xpr \
1132 JSON_HEDLEY_DIAGNOSTIC_POP
1133# else
1134# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1135 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1136 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1137 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1138 xpr \
1139 JSON_HEDLEY_DIAGNOSTIC_POP
1140# endif
1141# else
1142# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1143 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1144 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1145 xpr \
1146 JSON_HEDLEY_DIAGNOSTIC_POP
1147# endif
1148# endif
1149#endif
1150#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1151 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1152#endif
1153
1154#if defined(JSON_HEDLEY_CONST_CAST)
1155 #undef JSON_HEDLEY_CONST_CAST
1156#endif
1157#if defined(__cplusplus)
1158# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1159#elif \
1160 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1161 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1162 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1163# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1164 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1165 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1166 ((T) (expr)); \
1167 JSON_HEDLEY_DIAGNOSTIC_POP \
1168 }))
1169#else
1170# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1171#endif
1172
1173#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1174 #undef JSON_HEDLEY_REINTERPRET_CAST
1175#endif
1176#if defined(__cplusplus)
1177 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1178#else
1179 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1180#endif
1181
1182#if defined(JSON_HEDLEY_STATIC_CAST)
1183 #undef JSON_HEDLEY_STATIC_CAST
1184#endif
1185#if defined(__cplusplus)
1186 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1187#else
1188 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1189#endif
1190
1191#if defined(JSON_HEDLEY_CPP_CAST)
1192 #undef JSON_HEDLEY_CPP_CAST
1193#endif
1194#if defined(__cplusplus)
1195# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1196# define JSON_HEDLEY_CPP_CAST(T, expr) \
1197 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1198 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1199 ((T) (expr)) \
1200 JSON_HEDLEY_DIAGNOSTIC_POP
1201# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1202# define JSON_HEDLEY_CPP_CAST(T, expr) \
1203 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1204 _Pragma("diag_suppress=Pe137") \
1205 JSON_HEDLEY_DIAGNOSTIC_POP
1206# else
1207# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1208# endif
1209#else
1210# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1211#endif
1212
1213#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1214 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1215#endif
1216#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1217 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1218#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1219 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1220#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1221 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1222#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1223 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1224#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1225 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1226#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1227 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1228#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1229 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1230#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1231 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1232#elif \
1233 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1234 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1235 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1236 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1237 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1238 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1239 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1240 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1241 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1242 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1243 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1244 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1245#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1246 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1247#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1248 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1249#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1250 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1251#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1252 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1253#else
1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1255#endif
1256
1257#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1258 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1259#endif
1260#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1261 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1262#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1263 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1264#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1265 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1266#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1267 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1268#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1269 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1270#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1271 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1272#elif \
1273 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1274 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1275 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1276 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1277 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1278#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1279 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1280#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1281 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1282#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1283 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1284#else
1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1286#endif
1287
1288#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1289 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1290#endif
1291#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1292 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1293#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1294 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1295#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1296 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1297#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1298 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1299#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1300 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1301#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1302 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1303#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1305#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1307#elif \
1308 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1309 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1310 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1311 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1312#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1313 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1314#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1315 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1316#else
1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1318#endif
1319
1320#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1321 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1322#endif
1323#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1324 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1325#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1326 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1327#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1328 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1329#else
1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1331#endif
1332
1333#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1334 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1335#endif
1336#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1337 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1338#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1339 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1340#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1341 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1342#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1343 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1344#else
1345 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1346#endif
1347
1348#if defined(JSON_HEDLEY_DEPRECATED)
1349 #undef JSON_HEDLEY_DEPRECATED
1350#endif
1351#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1352 #undef JSON_HEDLEY_DEPRECATED_FOR
1353#endif
1354#if \
1355 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1356 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1357 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1358 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1359#elif \
1360 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1361 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1362 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1363 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1364 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1365 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1366 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1367 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1368 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1369 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1370 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1371 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1372 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1373 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1374#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1375 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1376 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1377#elif \
1378 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1379 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1380 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1381 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1382 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1383 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1384 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1385 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1386 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1387 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1388 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1389 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1390 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1391 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1392 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1393 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1394 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1395 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1396#elif \
1397 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1398 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1399 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1400 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1401 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1402#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1403 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1404 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1405#else
1406 #define JSON_HEDLEY_DEPRECATED(since)
1407 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1408#endif
1409
1410#if defined(JSON_HEDLEY_UNAVAILABLE)
1411 #undef JSON_HEDLEY_UNAVAILABLE
1412#endif
1413#if \
1414 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1415 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1416 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1417 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1418 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1419#else
1420 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1421#endif
1422
1423#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1424 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1425#endif
1426#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1427 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1428#endif
1429#if \
1430 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1431 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1432 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1433 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1434 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1435 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1436 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1437 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1438 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1439 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1440 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1441 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1442 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1443 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1444 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1445 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1446 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1447 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1448 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1449#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1450 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1451 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1452#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1453 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1454 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1455#elif defined(_Check_return_) /* SAL */
1456 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1457 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1458#else
1459 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1460 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1461#endif
1462
1463#if defined(JSON_HEDLEY_SENTINEL)
1464 #undef JSON_HEDLEY_SENTINEL
1465#endif
1466#if \
1467 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1468 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1469 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1470 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1471 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1472 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1473#else
1474 #define JSON_HEDLEY_SENTINEL(position)
1475#endif
1476
1477#if defined(JSON_HEDLEY_NO_RETURN)
1478 #undef JSON_HEDLEY_NO_RETURN
1479#endif
1480#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1481 #define JSON_HEDLEY_NO_RETURN __noreturn
1482#elif \
1483 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1484 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1485 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1486#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1487 #define JSON_HEDLEY_NO_RETURN _Noreturn
1488#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1489 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1490#elif \
1491 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1492 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1493 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1494 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1495 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1496 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1497 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1498 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1499 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1500 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1501 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1502 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1503 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1504 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1505 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1506 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1507 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1508 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1509#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1510 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1511#elif \
1512 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1513 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1514 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1515#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1516 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1517#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1518 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1519#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1520 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1521#else
1522 #define JSON_HEDLEY_NO_RETURN
1523#endif
1524
1525#if defined(JSON_HEDLEY_NO_ESCAPE)
1526 #undef JSON_HEDLEY_NO_ESCAPE
1527#endif
1528#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1529 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1530#else
1531 #define JSON_HEDLEY_NO_ESCAPE
1532#endif
1533
1534#if defined(JSON_HEDLEY_UNREACHABLE)
1535 #undef JSON_HEDLEY_UNREACHABLE
1536#endif
1537#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1538 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1539#endif
1540#if defined(JSON_HEDLEY_ASSUME)
1541 #undef JSON_HEDLEY_ASSUME
1542#endif
1543#if \
1544 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1545 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1546 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1547 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1548#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1549 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1550#elif \
1551 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1552 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1553 #if defined(__cplusplus)
1554 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1555 #else
1556 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1557 #endif
1558#endif
1559#if \
1560 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1561 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1562 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1563 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1564 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1565 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1566 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1567 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1568#elif defined(JSON_HEDLEY_ASSUME)
1569 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1570#endif
1571#if !defined(JSON_HEDLEY_ASSUME)
1572 #if defined(JSON_HEDLEY_UNREACHABLE)
1573 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1574 #else
1575 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1576 #endif
1577#endif
1578#if defined(JSON_HEDLEY_UNREACHABLE)
1579 #if \
1580 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1581 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1582 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1583 #else
1584 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1585 #endif
1586#else
1587 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1588#endif
1589#if !defined(JSON_HEDLEY_UNREACHABLE)
1590 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1591#endif
1592
1594#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1595 #pragma clang diagnostic ignored "-Wpedantic"
1596#endif
1597#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1598 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1599#endif
1600#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1601 #if defined(__clang__)
1602 #pragma clang diagnostic ignored "-Wvariadic-macros"
1603 #elif defined(JSON_HEDLEY_GCC_VERSION)
1604 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1605 #endif
1606#endif
1607#if defined(JSON_HEDLEY_NON_NULL)
1608 #undef JSON_HEDLEY_NON_NULL
1609#endif
1610#if \
1611 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1612 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1613 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1614 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1615 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1616#else
1617 #define JSON_HEDLEY_NON_NULL(...)
1618#endif
1620
1621#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1622 #undef JSON_HEDLEY_PRINTF_FORMAT
1623#endif
1624#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1625 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1626#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1627 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1628#elif \
1629 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1630 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1631 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1632 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1633 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1634 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1635 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1636 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1637 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1638 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1639 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1640 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1641 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1642 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1643 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1644 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1645 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1646 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1647#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1648 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1649#else
1650 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1651#endif
1652
1653#if defined(JSON_HEDLEY_CONSTEXPR)
1654 #undef JSON_HEDLEY_CONSTEXPR
1655#endif
1656#if defined(__cplusplus)
1657 #if __cplusplus >= 201103L
1658 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1659 #endif
1660#endif
1661#if !defined(JSON_HEDLEY_CONSTEXPR)
1662 #define JSON_HEDLEY_CONSTEXPR
1663#endif
1664
1665#if defined(JSON_HEDLEY_PREDICT)
1666 #undef JSON_HEDLEY_PREDICT
1667#endif
1668#if defined(JSON_HEDLEY_LIKELY)
1669 #undef JSON_HEDLEY_LIKELY
1670#endif
1671#if defined(JSON_HEDLEY_UNLIKELY)
1672 #undef JSON_HEDLEY_UNLIKELY
1673#endif
1674#if defined(JSON_HEDLEY_UNPREDICTABLE)
1675 #undef JSON_HEDLEY_UNPREDICTABLE
1676#endif
1677#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1678 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1679#endif
1680#if \
1681 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1682 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1683 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1684# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1685# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1686# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1687# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1688# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1689#elif \
1690 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1691 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1692 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1693 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1694 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1695 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1696 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1697 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1698 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1699 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1700 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1701 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1702 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1703 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1704 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1705 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1706# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1707 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1708# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1709 (__extension__ ({ \
1710 double hedley_probability_ = (probability); \
1711 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1712 }))
1713# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1714 (__extension__ ({ \
1715 double hedley_probability_ = (probability); \
1716 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1717 }))
1718# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1719# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1720#else
1721# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1722# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1723# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1724# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1725# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1726#endif
1727#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1728 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1729#endif
1730
1731#if defined(JSON_HEDLEY_MALLOC)
1732 #undef JSON_HEDLEY_MALLOC
1733#endif
1734#if \
1735 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1736 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1737 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1738 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1739 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1740 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1741 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1742 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1743 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1744 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1745 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1746 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1747 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1748 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1749 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1750 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1751 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1752 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1753 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1754#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1755 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1756#elif \
1757 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1758 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1759 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1760#else
1761 #define JSON_HEDLEY_MALLOC
1762#endif
1763
1764#if defined(JSON_HEDLEY_PURE)
1765 #undef JSON_HEDLEY_PURE
1766#endif
1767#if \
1768 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1769 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1770 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1771 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1772 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1773 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1774 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1775 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1776 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1777 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1778 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1779 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1780 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1781 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1782 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1783 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1784 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1785 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1786 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1787# define JSON_HEDLEY_PURE __attribute__((__pure__))
1788#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1789# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1790#elif defined(__cplusplus) && \
1791 ( \
1792 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1793 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1794 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1795 )
1796# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1797#else
1798# define JSON_HEDLEY_PURE
1799#endif
1800
1801#if defined(JSON_HEDLEY_CONST)
1802 #undef JSON_HEDLEY_CONST
1803#endif
1804#if \
1805 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1806 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1807 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1808 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1809 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1810 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1811 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1812 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1813 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1814 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1815 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1816 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1817 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1818 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1819 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1820 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1821 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1822 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1823 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1824 #define JSON_HEDLEY_CONST __attribute__((__const__))
1825#elif \
1826 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1827 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1828#else
1829 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1830#endif
1831
1832#if defined(JSON_HEDLEY_RESTRICT)
1833 #undef JSON_HEDLEY_RESTRICT
1834#endif
1835#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1836 #define JSON_HEDLEY_RESTRICT restrict
1837#elif \
1838 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1839 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1840 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1841 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1842 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1843 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1844 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1845 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1846 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1847 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1848 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1849 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1850 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1851 defined(__clang__) || \
1852 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1853 #define JSON_HEDLEY_RESTRICT __restrict
1854#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1855 #define JSON_HEDLEY_RESTRICT _Restrict
1856#else
1857 #define JSON_HEDLEY_RESTRICT
1858#endif
1859
1860#if defined(JSON_HEDLEY_INLINE)
1861 #undef JSON_HEDLEY_INLINE
1862#endif
1863#if \
1864 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1865 (defined(__cplusplus) && (__cplusplus >= 199711L))
1866 #define JSON_HEDLEY_INLINE inline
1867#elif \
1868 defined(JSON_HEDLEY_GCC_VERSION) || \
1869 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1870 #define JSON_HEDLEY_INLINE __inline__
1871#elif \
1872 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1873 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1874 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1875 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1876 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1877 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1878 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1879 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1880 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1881 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1882 #define JSON_HEDLEY_INLINE __inline
1883#else
1884 #define JSON_HEDLEY_INLINE
1885#endif
1886
1887#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1888 #undef JSON_HEDLEY_ALWAYS_INLINE
1889#endif
1890#if \
1891 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1892 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1893 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1894 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1895 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1896 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1897 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1898 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1899 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1900 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1901 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1902 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1903 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1904 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1905 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1906 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1907 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1908 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1909 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1910# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1911#elif \
1912 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1913 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1914# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1915#elif defined(__cplusplus) && \
1916 ( \
1917 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1918 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1919 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1920 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1921 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1922 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1923 )
1924# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1925#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1926# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1927#else
1928# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1929#endif
1930
1931#if defined(JSON_HEDLEY_NEVER_INLINE)
1932 #undef JSON_HEDLEY_NEVER_INLINE
1933#endif
1934#if \
1935 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1936 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1937 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1938 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1939 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1940 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1941 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1942 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1943 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1944 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1945 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1946 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1947 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1948 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1949 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1950 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1951 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1952 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1953 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1954 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1955#elif \
1956 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1957 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1958 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1959#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1960 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1961#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1962 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1963#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1964 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1965#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1966 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1967#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1968 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1969#else
1970 #define JSON_HEDLEY_NEVER_INLINE
1971#endif
1972
1973#if defined(JSON_HEDLEY_PRIVATE)
1974 #undef JSON_HEDLEY_PRIVATE
1975#endif
1976#if defined(JSON_HEDLEY_PUBLIC)
1977 #undef JSON_HEDLEY_PUBLIC
1978#endif
1979#if defined(JSON_HEDLEY_IMPORT)
1980 #undef JSON_HEDLEY_IMPORT
1981#endif
1982#if defined(_WIN32) || defined(__CYGWIN__)
1983# define JSON_HEDLEY_PRIVATE
1984# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1985# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1986#else
1987# if \
1988 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1989 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1990 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1991 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1992 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1993 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1994 ( \
1995 defined(__TI_EABI__) && \
1996 ( \
1997 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1998 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1999 ) \
2000 ) || \
2001 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2002# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
2003# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
2004# else
2005# define JSON_HEDLEY_PRIVATE
2006# define JSON_HEDLEY_PUBLIC
2007# endif
2008# define JSON_HEDLEY_IMPORT extern
2009#endif
2010
2011#if defined(JSON_HEDLEY_NO_THROW)
2012 #undef JSON_HEDLEY_NO_THROW
2013#endif
2014#if \
2015 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2016 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2017 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2018 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2019 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2020#elif \
2021 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2022 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2023 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2024 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2025#else
2026 #define JSON_HEDLEY_NO_THROW
2027#endif
2028
2029#if defined(JSON_HEDLEY_FALL_THROUGH)
2030 #undef JSON_HEDLEY_FALL_THROUGH
2031#endif
2032#if \
2033 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2034 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2035 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2036 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2037#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2038 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2039#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2040 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2041#elif defined(__fallthrough) /* SAL */
2042 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2043#else
2044 #define JSON_HEDLEY_FALL_THROUGH
2045#endif
2046
2047#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2048 #undef JSON_HEDLEY_RETURNS_NON_NULL
2049#endif
2050#if \
2051 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2052 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2053 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2054 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2055#elif defined(_Ret_notnull_) /* SAL */
2056 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2057#else
2058 #define JSON_HEDLEY_RETURNS_NON_NULL
2059#endif
2060
2061#if defined(JSON_HEDLEY_ARRAY_PARAM)
2062 #undef JSON_HEDLEY_ARRAY_PARAM
2063#endif
2064#if \
2065 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2066 !defined(__STDC_NO_VLA__) && \
2067 !defined(__cplusplus) && \
2068 !defined(JSON_HEDLEY_PGI_VERSION) && \
2069 !defined(JSON_HEDLEY_TINYC_VERSION)
2070 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2071#else
2072 #define JSON_HEDLEY_ARRAY_PARAM(name)
2073#endif
2074
2075#if defined(JSON_HEDLEY_IS_CONSTANT)
2076 #undef JSON_HEDLEY_IS_CONSTANT
2077#endif
2078#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2079 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2080#endif
2081/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2082 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2083#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2084 #undef JSON_HEDLEY_IS_CONSTEXPR_
2085#endif
2086#if \
2087 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2088 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2089 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2090 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2091 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2092 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2093 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2094 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2095 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2096 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2097 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2098#endif
2099#if !defined(__cplusplus)
2100# if \
2101 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2102 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2103 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2104 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2105 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2106 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2107 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2108#if defined(__INTPTR_TYPE__)
2109 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2110#else
2111 #include <stdint.h>
2112 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2113#endif
2114# elif \
2115 ( \
2116 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2117 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2118 !defined(JSON_HEDLEY_PGI_VERSION) && \
2119 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2120 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2121 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2122 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2123 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2124 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2125#if defined(__INTPTR_TYPE__)
2126 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2127#else
2128 #include <stdint.h>
2129 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2130#endif
2131# elif \
2132 defined(JSON_HEDLEY_GCC_VERSION) || \
2133 defined(JSON_HEDLEY_INTEL_VERSION) || \
2134 defined(JSON_HEDLEY_TINYC_VERSION) || \
2135 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2136 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2137 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2138 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2139 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2140 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2141 defined(__clang__)
2142# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2143 sizeof(void) != \
2144 sizeof(*( \
2145 1 ? \
2146 ((void*) ((expr) * 0L) ) : \
2147((struct { char v[sizeof(void) * 2]; } *) 1) \
2148 ) \
2149 ) \
2150 )
2151# endif
2152#endif
2153#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2154 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2155 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2156 #endif
2157 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2158#else
2159 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2160 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2161 #endif
2162 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2163#endif
2164
2165#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2166 #undef JSON_HEDLEY_BEGIN_C_DECLS
2167#endif
2168#if defined(JSON_HEDLEY_END_C_DECLS)
2169 #undef JSON_HEDLEY_END_C_DECLS
2170#endif
2171#if defined(JSON_HEDLEY_C_DECL)
2172 #undef JSON_HEDLEY_C_DECL
2173#endif
2174#if defined(__cplusplus)
2175 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2176 #define JSON_HEDLEY_END_C_DECLS }
2177 #define JSON_HEDLEY_C_DECL extern "C"
2178#else
2179 #define JSON_HEDLEY_BEGIN_C_DECLS
2180 #define JSON_HEDLEY_END_C_DECLS
2181 #define JSON_HEDLEY_C_DECL
2182#endif
2183
2184#if defined(JSON_HEDLEY_STATIC_ASSERT)
2185 #undef JSON_HEDLEY_STATIC_ASSERT
2186#endif
2187#if \
2188 !defined(__cplusplus) && ( \
2189 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2190 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2191 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2192 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2193 defined(_Static_assert) \
2194 )
2195# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2196#elif \
2197 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2198 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2199 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2200# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2201#else
2202# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2203#endif
2204
2205#if defined(JSON_HEDLEY_NULL)
2206 #undef JSON_HEDLEY_NULL
2207#endif
2208#if defined(__cplusplus)
2209 #if __cplusplus >= 201103L
2210 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2211 #elif defined(NULL)
2212 #define JSON_HEDLEY_NULL NULL
2213 #else
2214 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2215 #endif
2216#elif defined(NULL)
2217 #define JSON_HEDLEY_NULL NULL
2218#else
2219 #define JSON_HEDLEY_NULL ((void*) 0)
2220#endif
2221
2222#if defined(JSON_HEDLEY_MESSAGE)
2223 #undef JSON_HEDLEY_MESSAGE
2224#endif
2225#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2226# define JSON_HEDLEY_MESSAGE(msg) \
2227 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2228 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2229 JSON_HEDLEY_PRAGMA(message msg) \
2230 JSON_HEDLEY_DIAGNOSTIC_POP
2231#elif \
2232 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2233 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2234# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2235#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2236# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2237#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2238# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2239#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2240# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2241#else
2242# define JSON_HEDLEY_MESSAGE(msg)
2243#endif
2244
2245#if defined(JSON_HEDLEY_WARNING)
2246 #undef JSON_HEDLEY_WARNING
2247#endif
2248#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2249# define JSON_HEDLEY_WARNING(msg) \
2250 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2251 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2252 JSON_HEDLEY_PRAGMA(clang warning msg) \
2253 JSON_HEDLEY_DIAGNOSTIC_POP
2254#elif \
2255 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2256 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2257 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2258# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2259#elif \
2260 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2261 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2262# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2263#else
2264# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2265#endif
2266
2267#if defined(JSON_HEDLEY_REQUIRE)
2268 #undef JSON_HEDLEY_REQUIRE
2269#endif
2270#if defined(JSON_HEDLEY_REQUIRE_MSG)
2271 #undef JSON_HEDLEY_REQUIRE_MSG
2272#endif
2273#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2274# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2275# define JSON_HEDLEY_REQUIRE(expr) \
2276 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2277 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2278 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2279 JSON_HEDLEY_DIAGNOSTIC_POP
2280# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2281 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2282 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2283 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2284 JSON_HEDLEY_DIAGNOSTIC_POP
2285# else
2286# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2287# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2288# endif
2289#else
2290# define JSON_HEDLEY_REQUIRE(expr)
2291# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2292#endif
2293
2294#if defined(JSON_HEDLEY_FLAGS)
2295 #undef JSON_HEDLEY_FLAGS
2296#endif
2297#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2298 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2299#else
2300 #define JSON_HEDLEY_FLAGS
2301#endif
2302
2303#if defined(JSON_HEDLEY_FLAGS_CAST)
2304 #undef JSON_HEDLEY_FLAGS_CAST
2305#endif
2306#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2307# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2308 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2309 _Pragma("warning(disable:188)") \
2310 ((T) (expr)); \
2311 JSON_HEDLEY_DIAGNOSTIC_POP \
2312 }))
2313#else
2314# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2315#endif
2316
2317#if defined(JSON_HEDLEY_EMPTY_BASES)
2318 #undef JSON_HEDLEY_EMPTY_BASES
2319#endif
2320#if \
2321 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2322 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2323 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2324#else
2325 #define JSON_HEDLEY_EMPTY_BASES
2326#endif
2327
2328/* Remaining macros are deprecated. */
2329
2330#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2331 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2332#endif
2333#if defined(__clang__)
2334 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2335#else
2336 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2337#endif
2338
2339#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2340 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2341#endif
2342#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2343
2344#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2345 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2346#endif
2347#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2348
2349#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2350 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2351#endif
2352#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2353
2354#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2355 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2356#endif
2357#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2358
2359#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2360 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2361#endif
2362#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2363
2364#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2365 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2366#endif
2367#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2368
2369#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2370 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2371#endif
2372#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2373
2374#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2375
2376
2377// This file contains all internal macro definitions (except those affecting ABI)
2378// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2379
2380// #include <nlohmann/detail/abi_macros.hpp>
2381
2382
2383// exclude unsupported compilers
2384#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2385 #if defined(__clang__)
2386 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2387 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2388 #endif
2389 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2390 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2391 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2392 #endif
2393 #endif
2394#endif
2395
2396// C++ language standard detection
2397// if the user manually specified the used C++ version, this is skipped
2398#if !defined(JSON_HAS_CPP_26) && !defined(JSON_HAS_CPP_23) && !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2399 #if (defined(__cplusplus) && __cplusplus > 202302L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202302L)
2400 #define JSON_HAS_CPP_26
2401 #define JSON_HAS_CPP_23
2402 #define JSON_HAS_CPP_20
2403 #define JSON_HAS_CPP_17
2404 #define JSON_HAS_CPP_14
2405 #elif (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
2406 #define JSON_HAS_CPP_23
2407 #define JSON_HAS_CPP_20
2408 #define JSON_HAS_CPP_17
2409 #define JSON_HAS_CPP_14
2410 #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
2411 #define JSON_HAS_CPP_20
2412 #define JSON_HAS_CPP_17
2413 #define JSON_HAS_CPP_14
2414 #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2415 #define JSON_HAS_CPP_17
2416 #define JSON_HAS_CPP_14
2417 #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2418 #define JSON_HAS_CPP_14
2419 #endif
2420 // the cpp 11 flag is always specified because it is the minimal required version
2421 #define JSON_HAS_CPP_11
2422#endif
2423
2424#ifdef __has_include
2425 #if __has_include(<version>)
2426 #include <version>
2427 #endif
2428#endif
2429
2430#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2431 #ifdef JSON_HAS_CPP_17
2432 #if defined(__cpp_lib_filesystem)
2433 #define JSON_HAS_FILESYSTEM 1
2434 #elif defined(__cpp_lib_experimental_filesystem)
2435 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2436 #elif !defined(__has_include)
2437 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2438 #elif __has_include(<filesystem>)
2439 #define JSON_HAS_FILESYSTEM 1
2440 #elif __has_include(<experimental/filesystem>)
2441 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2442 #endif
2443
2444 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2445 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2446 #undef JSON_HAS_FILESYSTEM
2447 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2448 #endif
2449
2450 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2451 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2452 #undef JSON_HAS_FILESYSTEM
2453 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2454 #endif
2455
2456 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2457 #if defined(__clang_major__) && __clang_major__ < 7
2458 #undef JSON_HAS_FILESYSTEM
2459 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2460 #endif
2461
2462 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2463 #if defined(_MSC_VER) && _MSC_VER < 1914
2464 #undef JSON_HAS_FILESYSTEM
2465 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2466 #endif
2467
2468 // no filesystem support before iOS 13
2469 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2470 #undef JSON_HAS_FILESYSTEM
2471 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2472 #endif
2473
2474 // no filesystem support before macOS Catalina
2475 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2476 #undef JSON_HAS_FILESYSTEM
2477 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2478 #endif
2479 #endif
2480#endif
2481
2482#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2483 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2484#endif
2485
2486#ifndef JSON_HAS_FILESYSTEM
2487 #define JSON_HAS_FILESYSTEM 0
2488#endif
2489
2490#ifndef JSON_HAS_THREE_WAY_COMPARISON
2491 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2492 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2493 #define JSON_HAS_THREE_WAY_COMPARISON 1
2494 #else
2495 #define JSON_HAS_THREE_WAY_COMPARISON 0
2496 #endif
2497#endif
2498
2499#ifndef JSON_HAS_RANGES
2500 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has a syntax error
2501 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2502 #define JSON_HAS_RANGES 0
2503 #elif defined(__cpp_lib_ranges)
2504 #define JSON_HAS_RANGES 1
2505 #else
2506 #define JSON_HAS_RANGES 0
2507 #endif
2508#endif
2509
2510#ifndef JSON_HAS_STATIC_RTTI
2511 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2512 #define JSON_HAS_STATIC_RTTI 1
2513 #else
2514 #define JSON_HAS_STATIC_RTTI 0
2515 #endif
2516#endif
2517
2518#ifdef JSON_HAS_CPP_17
2519 #define JSON_INLINE_VARIABLE inline
2520#else
2521 #define JSON_INLINE_VARIABLE
2522#endif
2523
2524#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2525 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2526#else
2527 #define JSON_NO_UNIQUE_ADDRESS
2528#endif
2529
2530// disable documentation warnings on clang
2531#if defined(__clang__)
2532 #pragma clang diagnostic push
2533 #pragma clang diagnostic ignored "-Wdocumentation"
2534 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2535#endif
2536
2537// allow disabling exceptions
2538#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2539 #define JSON_THROW(exception) throw exception
2540 #define JSON_TRY try
2541 #define JSON_CATCH(exception) catch(exception)
2542 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2543#else
2544 #include <cstdlib>
2545 #define JSON_THROW(exception) std::abort()
2546 #define JSON_TRY if(true)
2547 #define JSON_CATCH(exception) if(false)
2548 #define JSON_INTERNAL_CATCH(exception) if(false)
2549#endif
2550
2551// override exception macros
2552#if defined(JSON_THROW_USER)
2553 #undef JSON_THROW
2554 #define JSON_THROW JSON_THROW_USER
2555#endif
2556#if defined(JSON_TRY_USER)
2557 #undef JSON_TRY
2558 #define JSON_TRY JSON_TRY_USER
2559#endif
2560#if defined(JSON_CATCH_USER)
2561 #undef JSON_CATCH
2562 #define JSON_CATCH JSON_CATCH_USER
2563 #undef JSON_INTERNAL_CATCH
2564 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2565#endif
2566#if defined(JSON_INTERNAL_CATCH_USER)
2567 #undef JSON_INTERNAL_CATCH
2568 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2569#endif
2570
2571// allow overriding assert
2572#if !defined(JSON_ASSERT)
2573 #include <cassert> // assert
2574 #define JSON_ASSERT(x) assert(x)
2575#endif
2576
2577// allow accessing some private functions (needed by the test suite)
2578#if defined(JSON_TESTS_PRIVATE)
2579 #define JSON_PRIVATE_UNLESS_TESTED public
2580#else
2581 #define JSON_PRIVATE_UNLESS_TESTED private
2582#endif
2583
2589#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2590 template<typename BasicJsonType> \
2591 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2592 { \
2593 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2594 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2595 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2596 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2597 auto it = std::find_if(std::begin(m), std::end(m), \
2598 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2599 { \
2600 return ej_pair.first == e; \
2601 }); \
2602 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2603 } \
2604 template<typename BasicJsonType> \
2605 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2606 { \
2607 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2608 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2609 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2610 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2611 auto it = std::find_if(std::begin(m), std::end(m), \
2612 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2613 { \
2614 return ej_pair.second == j; \
2615 }); \
2616 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2617 }
2618
2619// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2620// may be removed in the future once the class is split.
2621
2622#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2623 template<template<typename, typename, typename...> class ObjectType, \
2624 template<typename, typename...> class ArrayType, \
2625 class StringType, class BooleanType, class NumberIntegerType, \
2626 class NumberUnsignedType, class NumberFloatType, \
2627 template<typename> class AllocatorType, \
2628 template<typename, typename = void> class JSONSerializer, \
2629 class BinaryType, \
2630 class CustomBaseClass>
2631
2632#define NLOHMANN_BASIC_JSON_TPL \
2633 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2634 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2635 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2636
2637// Macros to simplify conversion from/to types
2638
2639#define NLOHMANN_JSON_EXPAND( x ) x
2640#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2641#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2642 NLOHMANN_JSON_PASTE64, \
2643 NLOHMANN_JSON_PASTE63, \
2644 NLOHMANN_JSON_PASTE62, \
2645 NLOHMANN_JSON_PASTE61, \
2646 NLOHMANN_JSON_PASTE60, \
2647 NLOHMANN_JSON_PASTE59, \
2648 NLOHMANN_JSON_PASTE58, \
2649 NLOHMANN_JSON_PASTE57, \
2650 NLOHMANN_JSON_PASTE56, \
2651 NLOHMANN_JSON_PASTE55, \
2652 NLOHMANN_JSON_PASTE54, \
2653 NLOHMANN_JSON_PASTE53, \
2654 NLOHMANN_JSON_PASTE52, \
2655 NLOHMANN_JSON_PASTE51, \
2656 NLOHMANN_JSON_PASTE50, \
2657 NLOHMANN_JSON_PASTE49, \
2658 NLOHMANN_JSON_PASTE48, \
2659 NLOHMANN_JSON_PASTE47, \
2660 NLOHMANN_JSON_PASTE46, \
2661 NLOHMANN_JSON_PASTE45, \
2662 NLOHMANN_JSON_PASTE44, \
2663 NLOHMANN_JSON_PASTE43, \
2664 NLOHMANN_JSON_PASTE42, \
2665 NLOHMANN_JSON_PASTE41, \
2666 NLOHMANN_JSON_PASTE40, \
2667 NLOHMANN_JSON_PASTE39, \
2668 NLOHMANN_JSON_PASTE38, \
2669 NLOHMANN_JSON_PASTE37, \
2670 NLOHMANN_JSON_PASTE36, \
2671 NLOHMANN_JSON_PASTE35, \
2672 NLOHMANN_JSON_PASTE34, \
2673 NLOHMANN_JSON_PASTE33, \
2674 NLOHMANN_JSON_PASTE32, \
2675 NLOHMANN_JSON_PASTE31, \
2676 NLOHMANN_JSON_PASTE30, \
2677 NLOHMANN_JSON_PASTE29, \
2678 NLOHMANN_JSON_PASTE28, \
2679 NLOHMANN_JSON_PASTE27, \
2680 NLOHMANN_JSON_PASTE26, \
2681 NLOHMANN_JSON_PASTE25, \
2682 NLOHMANN_JSON_PASTE24, \
2683 NLOHMANN_JSON_PASTE23, \
2684 NLOHMANN_JSON_PASTE22, \
2685 NLOHMANN_JSON_PASTE21, \
2686 NLOHMANN_JSON_PASTE20, \
2687 NLOHMANN_JSON_PASTE19, \
2688 NLOHMANN_JSON_PASTE18, \
2689 NLOHMANN_JSON_PASTE17, \
2690 NLOHMANN_JSON_PASTE16, \
2691 NLOHMANN_JSON_PASTE15, \
2692 NLOHMANN_JSON_PASTE14, \
2693 NLOHMANN_JSON_PASTE13, \
2694 NLOHMANN_JSON_PASTE12, \
2695 NLOHMANN_JSON_PASTE11, \
2696 NLOHMANN_JSON_PASTE10, \
2697 NLOHMANN_JSON_PASTE9, \
2698 NLOHMANN_JSON_PASTE8, \
2699 NLOHMANN_JSON_PASTE7, \
2700 NLOHMANN_JSON_PASTE6, \
2701 NLOHMANN_JSON_PASTE5, \
2702 NLOHMANN_JSON_PASTE4, \
2703 NLOHMANN_JSON_PASTE3, \
2704 NLOHMANN_JSON_PASTE2, \
2705 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2706#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2707#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2708#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2709#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2710#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2711#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2712#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2713#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2714#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2715#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2716#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2717#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2718#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2719#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2720#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2721#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2722#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2723#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2724#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2725#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2726#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2727#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2728#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2729#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2730#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2731#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2732#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2733#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2734#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2735#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2736#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2737#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2738#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2739#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2740#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2741#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2742#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2743#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2744#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2745#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2746#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2747#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2748#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2749#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2750#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2751#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2752#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2753#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2754#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2755#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2756#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2757#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2758#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2759#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2760#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2761#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2762#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2763#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2764#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2765#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2766#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2767#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2768#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2769
2770#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2771#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2772#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1;
2773
2780#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2781 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2782 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2783 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2784 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2785
2792#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2793 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2794 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2795 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2796 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2797
2804#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2805 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2806 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2807
2814#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2815 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2816 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2817 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2818 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2819
2826#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2827 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2828 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2829 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2830 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2831
2838#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2839 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2840 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2841
2848#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
2849 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2850 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2851 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2852 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2853
2860#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2861 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2862 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2863 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2864 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2865
2872#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2873 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2874 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2875
2882#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
2883 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2884 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2885 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2886 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2887
2894#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2895 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2896 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2897 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2898 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2899
2906#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2907 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2908 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2909
2910// inspired from https://stackoverflow.com/a/26745591
2911// allows calling any std function as if (e.g., with begin):
2912// using std::begin; begin(x);
2913//
2914// it allows using the detected idiom to retrieve the return type
2915// of such an expression
2916#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2917 namespace detail { \
2918 using std::std_name; \
2919 \
2920 template<typename... T> \
2921 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2922 } \
2923 \
2924 namespace detail2 { \
2925 struct std_name##_tag \
2926 { \
2927 }; \
2928 \
2929 template<typename... T> \
2930 std_name##_tag std_name(T&&...); \
2931 \
2932 template<typename... T> \
2933 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2934 \
2935 template<typename... T> \
2936 struct would_call_std_##std_name \
2937 { \
2938 static constexpr auto const value = ::nlohmann::detail:: \
2939 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2940 }; \
2941 } /* namespace detail2 */ \
2942 \
2943 template<typename... T> \
2944 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2945 { \
2946 }
2947
2948#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2949 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2950#endif
2951
2952#if JSON_USE_IMPLICIT_CONVERSIONS
2953 #define JSON_EXPLICIT
2954#else
2955 #define JSON_EXPLICIT explicit
2956#endif
2957
2958#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2959 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2960#endif
2961
2962#ifndef JSON_USE_GLOBAL_UDLS
2963 #define JSON_USE_GLOBAL_UDLS 1
2964#endif
2965
2966#if JSON_HAS_THREE_WAY_COMPARISON
2967 #include <compare> // partial_ordering
2968#endif
2969
2971namespace detail
2972{
2973
2975// JSON type enumeration //
2977
3015
3029#if JSON_HAS_THREE_WAY_COMPARISON
3030 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
3031#else
3032 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3033#endif
3034{
3035 static constexpr std::array<std::uint8_t, 9> order = {{
3036 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3037 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3038 6 /* binary */
3039 }
3040 };
3041
3042 const auto l_index = static_cast<std::size_t>(lhs);
3043 const auto r_index = static_cast<std::size_t>(rhs);
3044#if JSON_HAS_THREE_WAY_COMPARISON
3045 if (l_index < order.size() && r_index < order.size())
3046 {
3047 return order[l_index] <=> order[r_index]; // *NOPAD*
3048 }
3049 return std::partial_ordering::unordered;
3050#else
3051 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
3052#endif
3053}
3054
3055// GCC selects the built-in operator< over an operator rewritten from
3056// a user-defined spaceship operator
3057// Clang, MSVC, and ICC select the rewritten candidate
3058// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
3059#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
3060inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3061{
3062 return std::is_lt(lhs <=> rhs); // *NOPAD*
3063}
3064#endif
3065
3066} // namespace detail
3068
3069// #include <nlohmann/detail/string_escape.hpp>
3070// __ _____ _____ _____
3071// __| | __| | | | JSON for Modern C++
3072// | | |__ | | | | | | version 3.12.0
3073// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3074//
3075// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3076// SPDX-License-Identifier: MIT
3077
3078
3079
3080// #include <nlohmann/detail/abi_macros.hpp>
3081
3082
3084namespace detail
3085{
3086
3100template<typename StringType>
3101inline void replace_substring(StringType& s, const StringType& f,
3102 const StringType& t)
3103{
3104 JSON_ASSERT(!f.empty());
3105 for (auto pos = s.find(f); // find the first occurrence of f
3106 pos != StringType::npos; // make sure f was found
3107 s.replace(pos, f.size(), t), // replace with t, and
3108 pos = s.find(f, pos + t.size())) // find the next occurrence of f
3109 {}
3110}
3111
3119template<typename StringType>
3120inline StringType escape(StringType s)
3121{
3122 replace_substring(s, StringType{"~"}, StringType{"~0"});
3123 replace_substring(s, StringType{"/"}, StringType{"~1"});
3124 return s;
3125}
3126
3134template<typename StringType>
3135inline void unescape(StringType& s)
3136{
3137 replace_substring(s, StringType{"~1"}, StringType{"/"});
3138 replace_substring(s, StringType{"~0"}, StringType{"~"});
3139}
3140
3141} // namespace detail
3143
3144// #include <nlohmann/detail/input/position_t.hpp>
3145// __ _____ _____ _____
3146// __| | __| | | | JSON for Modern C++
3147// | | |__ | | | | | | version 3.12.0
3148// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3149//
3150// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3151// SPDX-License-Identifier: MIT
3152
3153
3154
3155#include <cstddef> // size_t
3156
3157// #include <nlohmann/detail/abi_macros.hpp>
3158
3159
3161namespace detail
3162{
3163
3166{
3168 std::size_t chars_read_total = 0;
3172 std::size_t lines_read = 0;
3173
3175 constexpr operator size_t() const
3176 {
3177 return chars_read_total;
3178 }
3179};
3180
3181} // namespace detail
3183
3184// #include <nlohmann/detail/macro_scope.hpp>
3185
3186// #include <nlohmann/detail/meta/cpp_future.hpp>
3187// __ _____ _____ _____
3188// __| | __| | | | JSON for Modern C++
3189// | | |__ | | | | | | version 3.12.0
3190// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3191//
3192// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3193// SPDX-FileCopyrightText: 2018 The Abseil Authors
3194// SPDX-License-Identifier: MIT
3195
3196
3197
3198#include <array> // array
3199#include <cstddef> // size_t
3200#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3201#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3202
3203// #include <nlohmann/detail/macro_scope.hpp>
3204
3205
3207namespace detail
3208{
3209
3210template<typename T>
3211using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3212
3213#ifdef JSON_HAS_CPP_14
3214
3215// the following utilities are natively available in C++14
3216using std::enable_if_t;
3217using std::index_sequence;
3218using std::make_index_sequence;
3219using std::index_sequence_for;
3220
3221#else
3222
3223// alias templates to reduce boilerplate
3224template<bool B, typename T = void>
3225using enable_if_t = typename std::enable_if<B, T>::type;
3226
3227// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3228// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3229
3231
3232// integer_sequence
3233//
3234// Class template representing a compile-time integer sequence. An instantiation
3235// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3236// type through its template arguments (which is a common need when
3237// working with C++11 variadic templates). `absl::integer_sequence` is designed
3238// to be a drop-in replacement for C++14's `std::integer_sequence`.
3239//
3240// Example:
3241//
3242// template< class T, T... Ints >
3243// void user_function(integer_sequence<T, Ints...>);
3244//
3245// int main()
3246// {
3247// // user_function's `T` will be deduced to `int` and `Ints...`
3248// // will be deduced to `0, 1, 2, 3, 4`.
3249// user_function(make_integer_sequence<int, 5>());
3250// }
3251template <typename T, T... Ints>
3253{
3254 using value_type = T;
3255 static constexpr std::size_t size() noexcept
3256 {
3257 return sizeof...(Ints);
3258 }
3259};
3260
3261// index_sequence
3262//
3263// A helper template for an `integer_sequence` of `size_t`,
3264// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3265// `std::index_sequence`.
3266template <size_t... Ints>
3267using index_sequence = integer_sequence<size_t, Ints...>;
3268
3270{
3271
3272template <typename Seq, size_t SeqSize, size_t Rem>
3273struct Extend;
3274
3275// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3276template <typename T, T... Ints, size_t SeqSize>
3277struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3278{
3279 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3280};
3281
3282template <typename T, T... Ints, size_t SeqSize>
3283struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3284{
3285 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3286};
3287
3288// Recursion helper for 'make_integer_sequence<T, N>'.
3289// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3290template <typename T, size_t N>
3291struct Gen
3292{
3293 using type =
3294 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3295};
3296
3297template <typename T>
3298struct Gen<T, 0>
3299{
3301};
3302
3303} // namespace utility_internal
3304
3305// Compile-time sequences of integers
3306
3307// make_integer_sequence
3308//
3309// This template alias is equivalent to
3310// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3311// replacement for C++14's `std::make_integer_sequence`.
3312template <typename T, T N>
3314
3315// make_index_sequence
3316//
3317// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3318// and is designed to be a drop-in replacement for C++14's
3319// `std::make_index_sequence`.
3320template <size_t N>
3322
3323// index_sequence_for
3324//
3325// Converts a typename pack into an index sequence of the same length, and
3326// is designed to be a drop-in replacement for C++14's
3327// `std::index_sequence_for()`
3328template <typename... Ts>
3330
3332
3333#endif
3334
3335// dispatch utility (taken from ranges-v3)
3336template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3337template<> struct priority_tag<0> {};
3338
3339// taken from ranges-v3
3340template<typename T>
3342{
3343 static JSON_INLINE_VARIABLE constexpr T value{};
3344};
3345
3346#ifndef JSON_HAS_CPP_17
3347 template<typename T>
3349#endif
3350
3351template<typename T, typename... Args>
3352constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3353{
3354 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3355}
3356
3357} // namespace detail
3359
3360// #include <nlohmann/detail/meta/type_traits.hpp>
3361// __ _____ _____ _____
3362// __| | __| | | | JSON for Modern C++
3363// | | |__ | | | | | | version 3.12.0
3364// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3365//
3366// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3367// SPDX-License-Identifier: MIT
3368
3369
3370
3371#include <limits> // numeric_limits
3372#include <string> // char_traits
3373#include <tuple> // tuple
3374#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3375#include <utility> // declval
3376#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3377 #include <cstddef> // byte
3378#endif
3379// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3380// __ _____ _____ _____
3381// __| | __| | | | JSON for Modern C++
3382// | | |__ | | | | | | version 3.12.0
3383// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3384//
3385// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3386// SPDX-License-Identifier: MIT
3387
3388
3389
3390#include <iterator> // random_access_iterator_tag
3391
3392// #include <nlohmann/detail/abi_macros.hpp>
3393
3394// #include <nlohmann/detail/meta/void_t.hpp>
3395
3396// #include <nlohmann/detail/meta/cpp_future.hpp>
3397
3398
3400namespace detail
3401{
3402
3403template<typename It, typename = void>
3405
3406template<typename It>
3408 It,
3409 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3410 typename It::reference, typename It::iterator_category >>
3411{
3412 using difference_type = typename It::difference_type;
3413 using value_type = typename It::value_type;
3414 using pointer = typename It::pointer;
3415 using reference = typename It::reference;
3416 using iterator_category = typename It::iterator_category;
3417};
3418
3419// This is required as some compilers implement std::iterator_traits in a way that
3420// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3421template<typename T, typename = void>
3423{
3424};
3425
3426template<typename T>
3427struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3428 : iterator_types<T>
3429{
3430};
3431
3432template<typename T>
3434{
3435 using iterator_category = std::random_access_iterator_tag;
3436 using value_type = T;
3437 using difference_type = ptrdiff_t;
3438 using pointer = T*;
3439 using reference = T&;
3440};
3441
3442} // namespace detail
3444
3445// #include <nlohmann/detail/macro_scope.hpp>
3446
3447// #include <nlohmann/detail/meta/call_std/begin.hpp>
3448// __ _____ _____ _____
3449// __| | __| | | | JSON for Modern C++
3450// | | |__ | | | | | | version 3.12.0
3451// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3452//
3453// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3454// SPDX-License-Identifier: MIT
3455
3456
3457
3458// #include <nlohmann/detail/macro_scope.hpp>
3459
3460
3462
3464
3466
3467// #include <nlohmann/detail/meta/call_std/end.hpp>
3468// __ _____ _____ _____
3469// __| | __| | | | JSON for Modern C++
3470// | | |__ | | | | | | version 3.12.0
3471// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3472//
3473// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3474// SPDX-License-Identifier: MIT
3475
3476
3477
3478// #include <nlohmann/detail/macro_scope.hpp>
3479
3480
3482
3484
3486
3487// #include <nlohmann/detail/meta/cpp_future.hpp>
3488
3489// #include <nlohmann/detail/meta/detected.hpp>
3490
3491// #include <nlohmann/json_fwd.hpp>
3492// __ _____ _____ _____
3493// __| | __| | | | JSON for Modern C++
3494// | | |__ | | | | | | version 3.12.0
3495// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3496//
3497// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3498// SPDX-License-Identifier: MIT
3499
3500#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3501 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3502
3503 #include <cstdint> // int64_t, uint64_t
3504 #include <map> // map
3505 #include <memory> // allocator
3506 #include <string> // string
3507 #include <vector> // vector
3508
3509 // #include <nlohmann/detail/abi_macros.hpp>
3510
3511
3518
3526 template<typename T = void, typename SFINAE = void>
3527 struct adl_serializer;
3528
3531 template<template<typename U, typename V, typename... Args> class ObjectType =
3532 std::map,
3533 template<typename U, typename... Args> class ArrayType = std::vector,
3534 class StringType = std::string, class BooleanType = bool,
3535 class NumberIntegerType = std::int64_t,
3536 class NumberUnsignedType = std::uint64_t,
3537 class NumberFloatType = double,
3538 template<typename U> class AllocatorType = std::allocator,
3539 template<typename T, typename SFINAE = void> class JSONSerializer =
3541 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3542 class CustomBaseClass = void>
3543 class basic_json;
3544
3547 template<typename RefStringType>
3548 class json_pointer;
3549
3555
3558 template<class Key, class T, class IgnoredLess, class Allocator>
3559 struct ordered_map;
3560
3564
3566
3567#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3568
3569
3579namespace detail
3580{
3581
3583// helpers //
3585
3586// Note to maintainers:
3587//
3588// Every trait in this file expects a non-CV-qualified type.
3589// The only exceptions are in the 'aliases for detected' section
3590// (i.e., those of the form: decltype(T::member_function(std::declval<T>())))
3591//
3592// In this case, T has to be properly CV-qualified to constraint the function arguments
3593// (e.g., to_json(BasicJsonType&, const T&))
3594
3595template<typename> struct is_basic_json : std::false_type {};
3596
3598struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3599
3600// used by exceptions create() member functions
3601// true_type for the pointer to possibly cv-qualified basic_json or std::nullptr_t
3602// false_type otherwise
3603template<typename BasicJsonContext>
3605 std::integral_constant < bool,
3606 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3607 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3608{};
3609
3611// json_ref helpers //
3613
3614template<typename>
3615class json_ref;
3616
3617template<typename>
3618struct is_json_ref : std::false_type {};
3619
3620template<typename T>
3621struct is_json_ref<json_ref<T>> : std::true_type {};
3622
3624// aliases for detected //
3626
3627template<typename T>
3628using mapped_type_t = typename T::mapped_type;
3629
3630template<typename T>
3631using key_type_t = typename T::key_type;
3632
3633template<typename T>
3634using value_type_t = typename T::value_type;
3635
3636template<typename T>
3637using difference_type_t = typename T::difference_type;
3638
3639template<typename T>
3640using pointer_t = typename T::pointer;
3641
3642template<typename T>
3643using reference_t = typename T::reference;
3644
3645template<typename T>
3646using iterator_category_t = typename T::iterator_category;
3647
3648template<typename T, typename... Args>
3649using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3650
3651template<typename T, typename... Args>
3652using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3653
3654template<typename T, typename U>
3655using get_template_function = decltype(std::declval<T>().template get<U>());
3656
3657// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3658template<typename BasicJsonType, typename T, typename = void>
3659struct has_from_json : std::false_type {};
3660
3661// trait checking if j.get<T> is valid
3662// use this trait instead of std::is_constructible or std::is_convertible,
3663// both rely on, or make use of implicit conversions, and thus fail when T
3664// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3665template <typename BasicJsonType, typename T>
3670
3671template<typename BasicJsonType, typename T>
3672struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3673{
3674 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3675
3676 static constexpr bool value =
3678 const BasicJsonType&, T&>::value;
3679};
3680
3681// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3682// this overload is used for non-default-constructible user-defined-types
3683template<typename BasicJsonType, typename T, typename = void>
3684struct has_non_default_from_json : std::false_type {};
3685
3686template<typename BasicJsonType, typename T>
3687struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3688{
3689 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3690
3691 static constexpr bool value =
3693 const BasicJsonType&>::value;
3694};
3695
3696// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3697// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3698template<typename BasicJsonType, typename T, typename = void>
3699struct has_to_json : std::false_type {};
3700
3701template<typename BasicJsonType, typename T>
3702struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3703{
3704 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3705
3706 static constexpr bool value =
3707 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3708 T>::value;
3709};
3710
3711template<typename T>
3712using detect_key_compare = typename T::key_compare;
3713
3714template<typename T>
3715struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3716
3717// obtains the actual object key comparator
3718template<typename BasicJsonType>
3720{
3721 using object_t = typename BasicJsonType::object_t;
3722 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3723 using type = typename std::conditional < has_key_compare<object_t>::value,
3724 typename object_t::key_compare, object_comparator_t>::type;
3725};
3726
3727template<typename BasicJsonType>
3729
3731// char_traits //
3733
3734// Primary template of char_traits calls std char_traits
3735template<typename T>
3736struct char_traits : std::char_traits<T>
3737{};
3738
3739// Explicitly define char traits for unsigned char since it is not standard
3740template<>
3741struct char_traits<unsigned char> : std::char_traits<char>
3742{
3743 using char_type = unsigned char;
3744 using int_type = uint64_t;
3745
3746 // Redefine to_int_type function
3747 static int_type to_int_type(char_type c) noexcept
3748 {
3749 return static_cast<int_type>(c);
3750 }
3751
3753 {
3754 return static_cast<char_type>(i);
3755 }
3756
3757 static constexpr int_type eof() noexcept
3758 {
3759 return static_cast<int_type>(std::char_traits<char>::eof());
3760 }
3761};
3762
3763// Explicitly define char traits for signed char since it is not standard
3764template<>
3765struct char_traits<signed char> : std::char_traits<char>
3766{
3767 using char_type = signed char;
3768 using int_type = uint64_t;
3769
3770 // Redefine to_int_type function
3771 static int_type to_int_type(char_type c) noexcept
3772 {
3773 return static_cast<int_type>(c);
3774 }
3775
3777 {
3778 return static_cast<char_type>(i);
3779 }
3780
3781 static constexpr int_type eof() noexcept
3782 {
3783 return static_cast<int_type>(std::char_traits<char>::eof());
3784 }
3785};
3786
3787#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3788template<>
3789struct char_traits<std::byte> : std::char_traits<char>
3790{
3791 using char_type = std::byte;
3792 using int_type = uint64_t;
3793
3794 static int_type to_int_type(char_type c) noexcept
3795 {
3796 return static_cast<int_type>(std::to_integer<unsigned char>(c));
3797 }
3798
3799 static char_type to_char_type(int_type i) noexcept
3800 {
3801 return std::byte(static_cast<unsigned char>(i));
3802 }
3803
3804 static constexpr int_type eof() noexcept
3805 {
3806 return static_cast<int_type>(std::char_traits<char>::eof());
3807 }
3808};
3809#endif
3810
3812// is_ functions //
3814
3815// https://en.cppreference.com/w/cpp/types/conjunction
3816template<class...> struct conjunction : std::true_type { };
3817template<class B> struct conjunction<B> : B { };
3818template<class B, class... Bn>
3819struct conjunction<B, Bn...>
3820: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3821
3822// https://en.cppreference.com/w/cpp/types/negation
3823template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3824
3825// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3826// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3827// This causes compile errors in e.g., Clang 3.5 or GCC 4.9.
3828template <typename T>
3829struct is_default_constructible : std::is_default_constructible<T> {};
3830
3831template <typename T1, typename T2>
3832struct is_default_constructible<std::pair<T1, T2>>
3833 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3834
3835template <typename T1, typename T2>
3836struct is_default_constructible<const std::pair<T1, T2>>
3837 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3838
3839template <typename... Ts>
3840struct is_default_constructible<std::tuple<Ts...>>
3841 : conjunction<is_default_constructible<Ts>...> {};
3842
3843template <typename... Ts>
3844struct is_default_constructible<const std::tuple<Ts...>>
3845 : conjunction<is_default_constructible<Ts>...> {};
3846
3847template <typename T, typename... Args>
3848struct is_constructible : std::is_constructible<T, Args...> {};
3849
3850template <typename T1, typename T2>
3851struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3852
3853template <typename T1, typename T2>
3854struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3855
3856template <typename... Ts>
3857struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3858
3859template <typename... Ts>
3860struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3861
3862template<typename T, typename = void>
3863struct is_iterator_traits : std::false_type {};
3864
3865template<typename T>
3879
3880template<typename T>
3882{
3883 private:
3884 using t_ref = typename std::add_lvalue_reference<T>::type;
3885
3886 using iterator = detected_t<result_of_begin, t_ref>;
3887 using sentinel = detected_t<result_of_end, t_ref>;
3888
3889 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3890 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3891 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3892 static constexpr auto is_iterator_begin =
3894
3895 public:
3896 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3897};
3898
3899template<typename R>
3900using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3901
3902template<typename T>
3904
3905// The following implementation of is_complete_type is taken from
3906// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3907// and is written by Xiang Fan who agreed to use it in this library.
3908
3909template<typename T, typename = void>
3910struct is_complete_type : std::false_type {};
3911
3912template<typename T>
3913struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3914
3915template<typename BasicJsonType, typename CompatibleObjectType,
3916 typename = void>
3917struct is_compatible_object_type_impl : std::false_type {};
3918
3919template<typename BasicJsonType, typename CompatibleObjectType>
3921 BasicJsonType, CompatibleObjectType,
3922 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3923 is_detected<key_type_t, CompatibleObjectType>::value >>
3924{
3925 using object_t = typename BasicJsonType::object_t;
3926
3927 // macOS's is_constructible does not play well with nonesuch...
3928 static constexpr bool value =
3929 is_constructible<typename object_t::key_type,
3930 typename CompatibleObjectType::key_type>::value &&
3931 is_constructible<typename object_t::mapped_type,
3932 typename CompatibleObjectType::mapped_type>::value;
3933};
3934
3935template<typename BasicJsonType, typename CompatibleObjectType>
3937 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3938
3939template<typename BasicJsonType, typename ConstructibleObjectType,
3940 typename = void>
3941struct is_constructible_object_type_impl : std::false_type {};
3942
3943template<typename BasicJsonType, typename ConstructibleObjectType>
3945 BasicJsonType, ConstructibleObjectType,
3946 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3947 is_detected<key_type_t, ConstructibleObjectType>::value >>
3948{
3949 using object_t = typename BasicJsonType::object_t;
3950
3951 static constexpr bool value =
3953 (std::is_move_assignable<ConstructibleObjectType>::value ||
3954 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3955 (is_constructible<typename ConstructibleObjectType::key_type,
3956 typename object_t::key_type>::value &&
3957 std::is_same <
3958 typename object_t::mapped_type,
3959 typename ConstructibleObjectType::mapped_type >::value)) ||
3960 (has_from_json<BasicJsonType,
3961 typename ConstructibleObjectType::mapped_type>::value ||
3963 BasicJsonType,
3964 typename ConstructibleObjectType::mapped_type >::value);
3965};
3966
3967template<typename BasicJsonType, typename ConstructibleObjectType>
3969 : is_constructible_object_type_impl<BasicJsonType,
3970 ConstructibleObjectType> {};
3971
3972template<typename BasicJsonType, typename CompatibleStringType>
3978
3979template<typename BasicJsonType, typename ConstructibleStringType>
3981{
3982 // launder type through decltype() to fix compilation failure on ICPC
3983#ifdef __INTEL_COMPILER
3984 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3985#else
3986 using laundered_type = ConstructibleStringType;
3987#endif
3988
3989 static constexpr auto value =
3990 conjunction <
3992 is_detected_exact<typename BasicJsonType::string_t::value_type,
3994};
3995
3996template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3997struct is_compatible_array_type_impl : std::false_type {};
3998
3999template<typename BasicJsonType, typename CompatibleArrayType>
4001 BasicJsonType, CompatibleArrayType,
4002 enable_if_t <
4003 is_detected<iterator_t, CompatibleArrayType>::value&&
4004 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
4005// special case for types like std::filesystem::path whose iterator's value_type are themselves
4006// c.f. https://github.com/nlohmann/json/pull/3073
4007 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
4008{
4009 static constexpr bool value =
4010 is_constructible<BasicJsonType,
4012};
4013
4014template<typename BasicJsonType, typename CompatibleArrayType>
4016 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
4017
4018template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
4019struct is_constructible_array_type_impl : std::false_type {};
4020
4021template<typename BasicJsonType, typename ConstructibleArrayType>
4023 BasicJsonType, ConstructibleArrayType,
4024 enable_if_t<std::is_same<ConstructibleArrayType,
4025 typename BasicJsonType::value_type>::value >>
4026 : std::true_type {};
4027
4028template<typename BasicJsonType, typename ConstructibleArrayType>
4030 BasicJsonType, ConstructibleArrayType,
4031 enable_if_t < !std::is_same<ConstructibleArrayType,
4032 typename BasicJsonType::value_type>::value&&
4033 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4034 is_default_constructible<ConstructibleArrayType>::value&&
4035(std::is_move_assignable<ConstructibleArrayType>::value ||
4036 std::is_copy_assignable<ConstructibleArrayType>::value)&&
4037is_detected<iterator_t, ConstructibleArrayType>::value&&
4038is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
4039is_detected<range_value_t, ConstructibleArrayType>::value&&
4040// special case for types like std::filesystem::path whose iterator's value_type are themselves
4041// c.f. https://github.com/nlohmann/json/pull/3073
4042!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
4044detected_t<range_value_t, ConstructibleArrayType >>::value >>
4045{
4047
4048 static constexpr bool value =
4049 std::is_same<value_type,
4050 typename BasicJsonType::array_t::value_type>::value ||
4051 has_from_json<BasicJsonType,
4054 BasicJsonType,
4056};
4057
4058template<typename BasicJsonType, typename ConstructibleArrayType>
4060 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
4061
4062template<typename RealIntegerType, typename CompatibleNumberIntegerType,
4063 typename = void>
4064struct is_compatible_integer_type_impl : std::false_type {};
4065
4066template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4068 RealIntegerType, CompatibleNumberIntegerType,
4069 enable_if_t < std::is_integral<RealIntegerType>::value&&
4070 std::is_integral<CompatibleNumberIntegerType>::value&&
4071 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
4072{
4073 // is there an assert somewhere on overflows?
4074 using RealLimits = std::numeric_limits<RealIntegerType>;
4075 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
4076
4077 static constexpr auto value =
4078 is_constructible<RealIntegerType,
4079 CompatibleNumberIntegerType>::value &&
4080 CompatibleLimits::is_integer &&
4081 RealLimits::is_signed == CompatibleLimits::is_signed;
4082};
4083
4084template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4086 : is_compatible_integer_type_impl<RealIntegerType,
4087 CompatibleNumberIntegerType> {};
4088
4089template<typename BasicJsonType, typename CompatibleType, typename = void>
4090struct is_compatible_type_impl: std::false_type {};
4091
4092template<typename BasicJsonType, typename CompatibleType>
4094 BasicJsonType, CompatibleType,
4095 enable_if_t<is_complete_type<CompatibleType>::value >>
4096{
4097 static constexpr bool value =
4099};
4100
4101template<typename BasicJsonType, typename CompatibleType>
4103 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
4104
4105template<typename T1, typename T2>
4106struct is_constructible_tuple : std::false_type {};
4107
4108template<typename T1, typename... Args>
4109struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
4110
4111template<typename BasicJsonType, typename T>
4112struct is_json_iterator_of : std::false_type {};
4113
4114template<typename BasicJsonType>
4115struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
4116
4117template<typename BasicJsonType>
4118struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
4119{};
4120
4121// checks if a given type T is a template specialization of Primary
4122template<template <typename...> class Primary, typename T>
4123struct is_specialization_of : std::false_type {};
4124
4125template<template <typename...> class Primary, typename... Args>
4126struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4127
4128template<typename T>
4130
4131// checks if A and B are comparable using Compare functor
4132template<typename Compare, typename A, typename B, typename = void>
4133struct is_comparable : std::false_type {};
4134
4135template<typename Compare, typename A, typename B>
4136struct is_comparable<Compare, A, B, void_t<
4137decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4138decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4139>> : std::true_type {};
4140
4141template<typename T>
4142using detect_is_transparent = typename T::is_transparent;
4143
4144// type trait to check if KeyType can be used as an object key (without a BasicJsonType)
4145// see is_usable_as_basic_json_key_type below
4146template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4147 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4148using is_usable_as_key_type = typename std::conditional <
4150 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4151 ObjectKeyType>::value)
4152 && (!RequireTransparentComparator
4153 || is_detected <detect_is_transparent, Comparator>::value)
4155 std::true_type,
4156 std::false_type >::type;
4157
4158// type trait to check if KeyType can be used as an object key
4159// true if:
4160// - KeyType is comparable with BasicJsonType::object_t::key_type
4161// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4162// - the comparator is transparent or RequireTransparentComparator is false
4163// - KeyType is not a JSON iterator or json_pointer
4164template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4165 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4166using is_usable_as_basic_json_key_type = typename std::conditional <
4167 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4168 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4169 RequireTransparentComparator, ExcludeObjectKeyType>::value
4171 std::true_type,
4172 std::false_type >::type;
4173
4174template<typename ObjectType, typename KeyType>
4175using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4176
4177// type trait to check if object_t has an erase() member functions accepting KeyType
4178template<typename BasicJsonType, typename KeyType>
4179using has_erase_with_key_type = typename std::conditional <
4180 is_detected <
4182 typename BasicJsonType::object_t, KeyType >::value,
4183 std::true_type,
4184 std::false_type >::type;
4185
4186// a naive helper to check if a type is an ordered_map (exploits the fact that
4187// ordered_map inherits capacity() from std::vector)
4188template <typename T>
4190{
4191 using one = char;
4192
4193 struct two
4194 {
4195 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4196 };
4197
4198 template <typename C> static one test( decltype(&C::capacity) ) ;
4199 template <typename C> static two test(...);
4200
4201 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4202};
4203
4204// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4205template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4207{
4208 return static_cast<T>(value);
4209}
4210
4211template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4213{
4214 return value;
4215}
4216
4217template<typename... Types>
4219
4220template<typename... Types>
4222
4223template<typename... Types>
4225
4226// there's a disjunction trait in another PR; replace when merged
4227template<typename... Types>
4228using same_sign = std::integral_constant < bool,
4229 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4230
4231template<typename OfType, typename T>
4232using never_out_of_range = std::integral_constant < bool,
4233 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4234 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4235
4236template<typename OfType, typename T,
4237 bool OfTypeSigned = std::is_signed<OfType>::value,
4238 bool TSigned = std::is_signed<T>::value>
4240
4241template<typename OfType, typename T>
4242struct value_in_range_of_impl2<OfType, T, false, false>
4243{
4244 static constexpr bool test(T val)
4245 {
4246 using CommonType = typename std::common_type<OfType, T>::type;
4247 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4248 }
4249};
4250
4251template<typename OfType, typename T>
4252struct value_in_range_of_impl2<OfType, T, true, false>
4253{
4254 static constexpr bool test(T val)
4255 {
4256 using CommonType = typename std::common_type<OfType, T>::type;
4257 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4258 }
4259};
4260
4261template<typename OfType, typename T>
4262struct value_in_range_of_impl2<OfType, T, false, true>
4263{
4264 static constexpr bool test(T val)
4265 {
4266 using CommonType = typename std::common_type<OfType, T>::type;
4267 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4268 }
4269};
4270
4271template<typename OfType, typename T>
4272struct value_in_range_of_impl2<OfType, T, true, true>
4273{
4274 static constexpr bool test(T val)
4275 {
4276 using CommonType = typename std::common_type<OfType, T>::type;
4277 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4278 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4279 }
4280};
4281
4282template<typename OfType, typename T,
4283 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4286
4287template<typename OfType, typename T>
4288struct value_in_range_of_impl1<OfType, T, false>
4289{
4290 static constexpr bool test(T val)
4291 {
4293 }
4294};
4295
4296template<typename OfType, typename T>
4297struct value_in_range_of_impl1<OfType, T, true>
4298{
4299 static constexpr bool test(T /*val*/)
4300 {
4301 return true;
4302 }
4303};
4304
4305template<typename OfType, typename T>
4306constexpr bool value_in_range_of(T val)
4307{
4309}
4310
4311template<bool Value>
4312using bool_constant = std::integral_constant<bool, Value>;
4313
4315// is_c_string
4317
4318namespace impl
4319{
4320
4321template<typename T>
4322constexpr bool is_c_string()
4323{
4324 using TUnExt = typename std::remove_extent<T>::type;
4325 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4326 using TUnPtr = typename std::remove_pointer<T>::type;
4327 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4328 return
4329 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4330 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4331}
4332
4333} // namespace impl
4334
4335// checks whether T is a [cv] char */[cv] char[] C string
4336template<typename T>
4337struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4338
4339template<typename T>
4341
4343// is_transparent
4345
4346namespace impl
4347{
4348
4349template<typename T>
4350constexpr bool is_transparent()
4351{
4353}
4354
4355} // namespace impl
4356
4357// checks whether T has a member named is_transparent
4358template<typename T>
4359struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4360
4362
4363} // namespace detail
4365
4366// #include <nlohmann/detail/string_concat.hpp>
4367// __ _____ _____ _____
4368// __| | __| | | | JSON for Modern C++
4369// | | |__ | | | | | | version 3.12.0
4370// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4371//
4372// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4373// SPDX-License-Identifier: MIT
4374
4375
4376
4377#include <cstring> // strlen
4378#include <string> // string
4379#include <utility> // forward
4380
4381// #include <nlohmann/detail/meta/cpp_future.hpp>
4382
4383// #include <nlohmann/detail/meta/detected.hpp>
4384
4385
4387namespace detail
4388{
4389
4390inline std::size_t concat_length()
4391{
4392 return 0;
4393}
4394
4395template<typename... Args>
4396inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4397
4398template<typename StringType, typename... Args>
4399inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4400
4401template<typename... Args>
4402inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4403{
4404 return 1 + concat_length(rest...);
4405}
4406
4407template<typename... Args>
4408inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4409{
4410 // cppcheck-suppress ignoredReturnValue
4411 return ::strlen(cstr) + concat_length(rest...);
4412}
4413
4414template<typename StringType, typename... Args>
4415inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4416{
4417 return str.size() + concat_length(rest...);
4418}
4419
4420template<typename OutStringType>
4421inline void concat_into(OutStringType& /*out*/)
4422{}
4423
4424template<typename StringType, typename Arg>
4425using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4426
4427template<typename StringType, typename Arg>
4429
4430template<typename StringType, typename Arg>
4431using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4432
4433template<typename StringType, typename Arg>
4435
4436template<typename StringType, typename Arg>
4437using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4438
4439template<typename StringType, typename Arg>
4441
4442template<typename StringType, typename Arg>
4443using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4444
4445template<typename StringType, typename Arg>
4447
4448template < typename OutStringType, typename Arg, typename... Args,
4449 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4451inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4452
4453template < typename OutStringType, typename Arg, typename... Args,
4454 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4457inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4458
4459template < typename OutStringType, typename Arg, typename... Args,
4460 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4464inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4465
4466template<typename OutStringType, typename Arg, typename... Args,
4468inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4469{
4470 out.append(std::forward<Arg>(arg));
4471 concat_into(out, std::forward<Args>(rest)...);
4472}
4473
4474template < typename OutStringType, typename Arg, typename... Args,
4475 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4476 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4477inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4478{
4479 out += std::forward<Arg>(arg);
4480 concat_into(out, std::forward<Args>(rest)...);
4481}
4482
4483template < typename OutStringType, typename Arg, typename... Args,
4484 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4485 && !detect_string_can_append_op<OutStringType, Arg>::value
4486 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4487inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4488{
4489 out.append(arg.begin(), arg.end());
4490 concat_into(out, std::forward<Args>(rest)...);
4491}
4492
4493template < typename OutStringType, typename Arg, typename... Args,
4494 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4495 && !detect_string_can_append_op<OutStringType, Arg>::value
4496 && !detect_string_can_append_iter<OutStringType, Arg>::value
4497 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4498inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4499{
4500 out.append(arg.data(), arg.size());
4501 concat_into(out, std::forward<Args>(rest)...);
4502}
4503
4504template<typename OutStringType = std::string, typename... Args>
4505inline OutStringType concat(Args && ... args)
4506{
4507 OutStringType str;
4508 str.reserve(concat_length(args...));
4509 concat_into(str, std::forward<Args>(args)...);
4510 return str;
4511}
4512
4513} // namespace detail
4515
4516
4517// With -Wweak-vtables, Clang will complain about the exception classes as they
4518// have no out-of-line virtual method definitions and their vtable will be
4519// emitted in every translation unit. This issue cannot be fixed with a
4520// header-only library as there is no implementation file to move these
4521// functions to. As a result, we suppress this warning here to avoid client
4522// code stumbling over this. See https://github.com/nlohmann/json/issues/4087
4523// for a discussion.
4524#if defined(__clang__)
4525 #pragma clang diagnostic push
4526 #pragma clang diagnostic ignored "-Wweak-vtables"
4527#endif
4528
4530namespace detail
4531{
4532
4534// exceptions //
4536
4539class exception : public std::exception
4540{
4541 public:
4543 const char* what() const noexcept override
4544 {
4545 return m.what();
4546 }
4547
4549 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4550
4551 protected:
4553 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4554
4555 static std::string name(const std::string& ename, int id_)
4556 {
4557 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4558 }
4559
4560 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4561 {
4562 return "";
4563 }
4564
4565 template<typename BasicJsonType>
4566 static std::string diagnostics(const BasicJsonType* leaf_element)
4567 {
4568#if JSON_DIAGNOSTICS
4569 std::vector<std::string> tokens;
4570 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4571 {
4572 switch (current->m_parent->type())
4573 {
4574 case value_t::array:
4575 {
4576 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4577 {
4578 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4579 {
4580 tokens.emplace_back(std::to_string(i));
4581 break;
4582 }
4583 }
4584 break;
4585 }
4586
4587 case value_t::object:
4588 {
4589 for (const auto& element : *current->m_parent->m_data.m_value.object)
4590 {
4591 if (&element.second == current)
4592 {
4593 tokens.emplace_back(element.first.c_str());
4594 break;
4595 }
4596 }
4597 break;
4598 }
4599
4600 case value_t::null: // LCOV_EXCL_LINE
4601 case value_t::string: // LCOV_EXCL_LINE
4602 case value_t::boolean: // LCOV_EXCL_LINE
4603 case value_t::number_integer: // LCOV_EXCL_LINE
4604 case value_t::number_unsigned: // LCOV_EXCL_LINE
4605 case value_t::number_float: // LCOV_EXCL_LINE
4606 case value_t::binary: // LCOV_EXCL_LINE
4607 case value_t::discarded: // LCOV_EXCL_LINE
4608 default: // LCOV_EXCL_LINE
4609 break; // LCOV_EXCL_LINE
4610 }
4611 }
4612
4613 if (tokens.empty())
4614 {
4615 return "";
4616 }
4617
4618 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4619 [](const std::string & a, const std::string & b)
4620 {
4621 return concat(a, '/', detail::escape(b));
4622 });
4623
4624 return concat('(', str, ") ", get_byte_positions(leaf_element));
4625#else
4626 return get_byte_positions(leaf_element);
4627#endif
4628 }
4629
4630 private:
4632 std::runtime_error m;
4633#if JSON_DIAGNOSTIC_POSITIONS
4634 template<typename BasicJsonType>
4635 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4636 {
4637 if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos))
4638 {
4639 return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
4640 }
4641 return "";
4642 }
4643#else
4644 template<typename BasicJsonType>
4645 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4646 {
4647 static_cast<void>(leaf_element);
4648 return "";
4649 }
4650#endif
4651};
4652
4655class parse_error : public exception
4656{
4657 public:
4667 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4668 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4669 {
4670 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4671 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4672 return {id_, pos.chars_read_total, w.c_str()};
4673 }
4674
4675 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4676 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4677 {
4678 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4679 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4680 ": ", exception::diagnostics(context), what_arg);
4681 return {id_, byte_, w.c_str()};
4682 }
4683
4693 const std::size_t byte;
4694
4695 private:
4696 parse_error(int id_, std::size_t byte_, const char* what_arg)
4697 : exception(id_, what_arg), byte(byte_) {}
4698
4699 static std::string position_string(const position_t& pos)
4700 {
4701 return concat(" at line ", std::to_string(pos.lines_read + 1),
4702 ", column ", std::to_string(pos.chars_read_current_line));
4703 }
4704};
4705
4708class invalid_iterator : public exception
4709{
4710 public:
4711 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4712 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4713 {
4714 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4715 return {id_, w.c_str()};
4716 }
4717
4718 private:
4720 invalid_iterator(int id_, const char* what_arg)
4721 : exception(id_, what_arg) {}
4722};
4723
4726class type_error : public exception
4727{
4728 public:
4729 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4730 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4731 {
4732 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4733 return {id_, w.c_str()};
4734 }
4735
4736 private:
4738 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4739};
4740
4743class out_of_range : public exception
4744{
4745 public:
4746 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4747 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4748 {
4749 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4750 return {id_, w.c_str()};
4751 }
4752
4753 private:
4755 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4756};
4757
4760class other_error : public exception
4761{
4762 public:
4763 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4764 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4765 {
4766 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4767 return {id_, w.c_str()};
4768 }
4769
4770 private:
4772 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4773};
4774
4775} // namespace detail
4777
4778#if defined(__clang__)
4779 #pragma clang diagnostic pop
4780#endif
4781
4782// #include <nlohmann/detail/macro_scope.hpp>
4783
4784// #include <nlohmann/detail/meta/cpp_future.hpp>
4785
4786// #include <nlohmann/detail/meta/identity_tag.hpp>
4787// __ _____ _____ _____
4788// __| | __| | | | JSON for Modern C++
4789// | | |__ | | | | | | version 3.12.0
4790// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4791//
4792// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4793// SPDX-License-Identifier: MIT
4794
4795
4796
4797// #include <nlohmann/detail/abi_macros.hpp>
4798
4799
4801namespace detail
4802{
4803
4804// dispatching helper struct
4805template <class T> struct identity_tag {};
4806
4807} // namespace detail
4809
4810// #include <nlohmann/detail/meta/std_fs.hpp>
4811// __ _____ _____ _____
4812// __| | __| | | | JSON for Modern C++
4813// | | |__ | | | | | | version 3.12.0
4814// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4815//
4816// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4817// SPDX-License-Identifier: MIT
4818
4819
4820
4821// #include <nlohmann/detail/macro_scope.hpp>
4822
4823
4824#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4825#include <experimental/filesystem>
4827namespace detail
4828{
4829namespace std_fs = std::experimental::filesystem;
4830} // namespace detail
4832#elif JSON_HAS_FILESYSTEM
4833#include <filesystem> // NOLINT(build/c++17)
4835namespace detail
4836{
4837namespace std_fs = std::filesystem;
4838} // namespace detail
4840#endif
4841
4842// #include <nlohmann/detail/meta/type_traits.hpp>
4843
4844// #include <nlohmann/detail/string_concat.hpp>
4845
4846// #include <nlohmann/detail/value_t.hpp>
4847
4848
4849// include after macro_scope.hpp
4850#ifdef JSON_HAS_CPP_17
4851 #include <optional> // optional
4852#endif
4853
4854#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4855 #include <string_view> // u8string_view
4856#endif
4857
4859namespace detail
4860{
4861
4862template<typename BasicJsonType>
4863inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4864{
4865 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4866 {
4867 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4868 }
4869 n = nullptr;
4870}
4871
4872#ifdef JSON_HAS_CPP_17
4873template<typename BasicJsonType, typename T>
4874void from_json(const BasicJsonType& j, std::optional<T>& opt)
4875{
4876 if (j.is_null())
4877 {
4878 opt = std::nullopt;
4879 }
4880 else
4881 {
4882 opt.emplace(j.template get<T>());
4883 }
4884}
4885#endif // JSON_HAS_CPP_17
4886
4887// overloads for basic_json template parameters
4888template < typename BasicJsonType, typename ArithmeticType,
4889 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4890 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4891 int > = 0 >
4892void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4893{
4894 switch (static_cast<value_t>(j))
4895 {
4897 {
4898 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4899 break;
4900 }
4902 {
4903 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4904 break;
4905 }
4907 {
4908 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4909 break;
4910 }
4911
4912 case value_t::null:
4913 case value_t::object:
4914 case value_t::array:
4915 case value_t::string:
4916 case value_t::boolean:
4917 case value_t::binary:
4918 case value_t::discarded:
4919 default:
4920 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4921 }
4922}
4923
4924template<typename BasicJsonType>
4925inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4926{
4927 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4928 {
4929 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4930 }
4931 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4932}
4933
4934template<typename BasicJsonType>
4935inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4936{
4937 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4938 {
4939 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4940 }
4941 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4942}
4943
4944template <
4945 typename BasicJsonType, typename StringType,
4946 enable_if_t <
4947 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4948 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4949 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4950 && !is_json_ref<StringType>::value, int > = 0 >
4951inline void from_json(const BasicJsonType& j, StringType& s)
4952{
4953 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4954 {
4955 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4956 }
4957
4958 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4959}
4960
4961template<typename BasicJsonType>
4962inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4963{
4964 get_arithmetic_value(j, val);
4965}
4966
4967template<typename BasicJsonType>
4968inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4969{
4970 get_arithmetic_value(j, val);
4971}
4972
4973template<typename BasicJsonType>
4974inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4975{
4976 get_arithmetic_value(j, val);
4977}
4978
4979#if !JSON_DISABLE_ENUM_SERIALIZATION
4980template<typename BasicJsonType, typename EnumType,
4981 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4982inline void from_json(const BasicJsonType& j, EnumType& e)
4983{
4984 typename std::underlying_type<EnumType>::type val;
4985 get_arithmetic_value(j, val);
4986 e = static_cast<EnumType>(val);
4987}
4988#endif // JSON_DISABLE_ENUM_SERIALIZATION
4989
4990// forward_list doesn't have an insert method
4991template<typename BasicJsonType, typename T, typename Allocator,
4992 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4993inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4994{
4995 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4996 {
4997 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4998 }
4999 l.clear();
5000 std::transform(j.rbegin(), j.rend(),
5001 std::front_inserter(l), [](const BasicJsonType & i)
5002 {
5003 return i.template get<T>();
5004 });
5005}
5006
5007// valarray doesn't have an insert method
5008template<typename BasicJsonType, typename T,
5009 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
5010inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
5011{
5012 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5013 {
5014 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5015 }
5016 l.resize(j.size());
5017 std::transform(j.begin(), j.end(), std::begin(l),
5018 [](const BasicJsonType & elem)
5019 {
5020 return elem.template get<T>();
5021 });
5022}
5023
5024template<typename BasicJsonType, typename T, std::size_t N>
5025auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5026-> decltype(j.template get<T>(), void())
5027{
5028 for (std::size_t i = 0; i < N; ++i)
5029 {
5030 arr[i] = j.at(i).template get<T>();
5031 }
5032}
5033
5034template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
5035auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5036-> decltype(j.template get<T>(), void())
5037{
5038 for (std::size_t i1 = 0; i1 < N1; ++i1)
5039 {
5040 for (std::size_t i2 = 0; i2 < N2; ++i2)
5041 {
5042 arr[i1][i2] = j.at(i1).at(i2).template get<T>();
5043 }
5044 }
5045}
5046
5047template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
5048auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5049-> decltype(j.template get<T>(), void())
5050{
5051 for (std::size_t i1 = 0; i1 < N1; ++i1)
5052 {
5053 for (std::size_t i2 = 0; i2 < N2; ++i2)
5054 {
5055 for (std::size_t i3 = 0; i3 < N3; ++i3)
5056 {
5057 arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
5058 }
5059 }
5060 }
5061}
5062
5063template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
5064auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5065-> decltype(j.template get<T>(), void())
5066{
5067 for (std::size_t i1 = 0; i1 < N1; ++i1)
5068 {
5069 for (std::size_t i2 = 0; i2 < N2; ++i2)
5070 {
5071 for (std::size_t i3 = 0; i3 < N3; ++i3)
5072 {
5073 for (std::size_t i4 = 0; i4 < N4; ++i4)
5074 {
5075 arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
5076 }
5077 }
5078 }
5079 }
5080}
5081
5082template<typename BasicJsonType>
5083inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
5084{
5085 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
5086}
5087
5088template<typename BasicJsonType, typename T, std::size_t N>
5089auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
5090 priority_tag<2> /*unused*/)
5091-> decltype(j.template get<T>(), void())
5092{
5093 for (std::size_t i = 0; i < N; ++i)
5094 {
5095 arr[i] = j.at(i).template get<T>();
5096 }
5097}
5098
5099template<typename BasicJsonType, typename ConstructibleArrayType,
5101 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5102 int> = 0>
5103auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
5104-> decltype(
5105 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
5107 void())
5108{
5109 using std::end;
5110
5111 ConstructibleArrayType ret;
5112 ret.reserve(j.size());
5113 std::transform(j.begin(), j.end(),
5114 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
5115 {
5116 // get<BasicJsonType>() returns *this, this won't call a from_json
5117 // method when value_type is BasicJsonType
5119 });
5120 arr = std::move(ret);
5121}
5122
5123template<typename BasicJsonType, typename ConstructibleArrayType,
5125 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5126 int> = 0>
5127inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
5128 priority_tag<0> /*unused*/)
5129{
5130 using std::end;
5131
5132 ConstructibleArrayType ret;
5133 std::transform(
5134 j.begin(), j.end(), std::inserter(ret, end(ret)),
5135 [](const BasicJsonType & i)
5136 {
5137 // get<BasicJsonType>() returns *this, this won't call a from_json
5138 // method when value_type is BasicJsonType
5140 });
5141 arr = std::move(ret);
5142}
5143
5144template < typename BasicJsonType, typename ConstructibleArrayType,
5145 enable_if_t <
5146 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
5147 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
5149 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
5150 !is_basic_json<ConstructibleArrayType>::value,
5151 int > = 0 >
5152auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
5153-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
5155void())
5156{
5157 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5158 {
5159 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5160 }
5161
5163}
5164
5165template < typename BasicJsonType, typename T, std::size_t... Idx >
5166std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
5167 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
5168{
5169 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
5170}
5171
5172template < typename BasicJsonType, typename T, std::size_t N >
5173auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
5174-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
5175{
5176 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5177 {
5178 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5179 }
5180
5181 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
5182}
5183
5184template<typename BasicJsonType>
5185inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
5186{
5187 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
5188 {
5189 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
5190 }
5191
5192 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
5193}
5194
5195template<typename BasicJsonType, typename ConstructibleObjectType,
5196 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5197inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5198{
5199 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5200 {
5201 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5202 }
5203
5204 ConstructibleObjectType ret;
5205 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5206 using value_type = typename ConstructibleObjectType::value_type;
5207 std::transform(
5208 inner_object->begin(), inner_object->end(),
5209 std::inserter(ret, ret.begin()),
5210 [](typename BasicJsonType::object_t::value_type const & p)
5211 {
5212 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5213 });
5214 obj = std::move(ret);
5215}
5216
5217// overload for arithmetic types, not chosen for basic_json template arguments
5218// (BooleanType, etc.); note: Is it really necessary to provide explicit
5219// overloads for boolean_t etc. in case of a custom BooleanType which is not
5220// an arithmetic type?
5221template < typename BasicJsonType, typename ArithmeticType,
5222 enable_if_t <
5223 std::is_arithmetic<ArithmeticType>::value&&
5224 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5225 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5226 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5227 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5228 int > = 0 >
5229inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5230{
5231 switch (static_cast<value_t>(j))
5232 {
5234 {
5235 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5236 break;
5237 }
5239 {
5240 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5241 break;
5242 }
5244 {
5245 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5246 break;
5247 }
5248 case value_t::boolean:
5249 {
5250 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5251 break;
5252 }
5253
5254 case value_t::null:
5255 case value_t::object:
5256 case value_t::array:
5257 case value_t::string:
5258 case value_t::binary:
5259 case value_t::discarded:
5260 default:
5261 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5262 }
5263}
5264
5265template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5266std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5267{
5268 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5269}
5270
5271template<typename BasicJsonType>
5272std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
5273{
5274 return {};
5275}
5276
5277template < typename BasicJsonType, class A1, class A2 >
5278std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5279{
5280 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5281 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5282}
5283
5284template<typename BasicJsonType, typename A1, typename A2>
5285inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5286{
5287 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5288}
5289
5290template<typename BasicJsonType, typename... Args>
5291std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5292{
5293 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5294}
5295
5296template<typename BasicJsonType, typename... Args>
5297inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5298{
5299 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5300}
5301
5302template<typename BasicJsonType, typename TupleRelated>
5303auto from_json(BasicJsonType&& j, TupleRelated&& t)
5304-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5305{
5306 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5307 {
5308 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5309 }
5310
5311 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5312}
5313
5314template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5315 typename = enable_if_t < !std::is_constructible <
5316 typename BasicJsonType::string_t, Key >::value >>
5317inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5318{
5319 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5320 {
5321 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5322 }
5323 m.clear();
5324 for (const auto& p : j)
5325 {
5326 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5327 {
5328 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5329 }
5330 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5331 }
5332}
5333
5334template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5335 typename = enable_if_t < !std::is_constructible <
5336 typename BasicJsonType::string_t, Key >::value >>
5337inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5338{
5339 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5340 {
5341 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5342 }
5343 m.clear();
5344 for (const auto& p : j)
5345 {
5346 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5347 {
5348 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5349 }
5350 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5351 }
5352}
5353
5354#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5355template<typename BasicJsonType>
5356inline void from_json(const BasicJsonType& j, std_fs::path& p)
5357{
5358 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5359 {
5360 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5361 }
5362 const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5363 // Checking for C++20 standard or later can be insufficient in case the
5364 // library support for char8_t is either incomplete or was disabled
5365 // altogether. Use the __cpp_lib_char8_t feature test instead.
5366#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201907L)
5367 p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
5368#else
5369 p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
5370#endif
5371}
5372#endif
5373
5375{
5376 template<typename BasicJsonType, typename T>
5377 auto operator()(const BasicJsonType& j, T&& val) const
5378 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5379 -> decltype(from_json(j, std::forward<T>(val)))
5380 {
5381 return from_json(j, std::forward<T>(val));
5382 }
5383};
5384
5385} // namespace detail
5386
5387#ifndef JSON_HAS_CPP_17
5391namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5392{
5393#endif
5394JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5396#ifndef JSON_HAS_CPP_17
5397} // namespace
5398#endif
5399
5401
5402// #include <nlohmann/detail/conversions/to_json.hpp>
5403// __ _____ _____ _____
5404// __| | __| | | | JSON for Modern C++
5405// | | |__ | | | | | | version 3.12.0
5406// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5407//
5408// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5409// SPDX-License-Identifier: MIT
5410
5411
5412
5413// #include <nlohmann/detail/macro_scope.hpp>
5414// JSON_HAS_CPP_17
5415#ifdef JSON_HAS_CPP_17
5416 #include <optional> // optional
5417#endif
5418
5419#include <algorithm> // copy
5420#include <iterator> // begin, end
5421#include <memory> // allocator_traits
5422#include <string> // basic_string, char_traits
5423#include <tuple> // tuple, get
5424#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5425#include <utility> // move, forward, declval, pair
5426#include <valarray> // valarray
5427#include <vector> // vector
5428
5429// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5430// __ _____ _____ _____
5431// __| | __| | | | JSON for Modern C++
5432// | | |__ | | | | | | version 3.12.0
5433// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5434//
5435// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5436// SPDX-License-Identifier: MIT
5437
5438
5439
5440#include <cstddef> // size_t
5441#include <iterator> // forward_iterator_tag
5442#include <tuple> // tuple_size, get, tuple_element
5443#include <utility> // move
5444
5445#if JSON_HAS_RANGES
5446 #include <ranges> // enable_borrowed_range
5447#endif
5448
5449// #include <nlohmann/detail/abi_macros.hpp>
5450
5451// #include <nlohmann/detail/meta/type_traits.hpp>
5452
5453// #include <nlohmann/detail/string_utils.hpp>
5454// __ _____ _____ _____
5455// __| | __| | | | JSON for Modern C++
5456// | | |__ | | | | | | version 3.12.0
5457// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5458//
5459// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5460// SPDX-License-Identifier: MIT
5461
5462
5463
5464#include <cstddef> // size_t
5465#include <string> // string, to_string
5466
5467// #include <nlohmann/detail/abi_macros.hpp>
5468
5469
5471namespace detail
5472{
5473
5474template<typename StringType>
5475void int_to_string(StringType& target, std::size_t value)
5476{
5477 // For ADL
5478 using std::to_string;
5479 target = to_string(value);
5480}
5481
5482template<typename StringType>
5483StringType to_string(std::size_t value)
5484{
5485 StringType result;
5486 int_to_string(result, value);
5487 return result;
5488}
5489
5490} // namespace detail
5492
5493// #include <nlohmann/detail/value_t.hpp>
5494
5495
5497namespace detail
5498{
5499
5500template<typename IteratorType> class iteration_proxy_value
5501{
5502 public:
5503 using difference_type = std::ptrdiff_t;
5507 using iterator_category = std::forward_iterator_tag;
5508 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5509
5510 private:
5512 IteratorType anchor{};
5514 std::size_t array_index = 0;
5516 mutable std::size_t array_index_last = 0;
5518 mutable string_type array_index_str = "0";
5520 string_type empty_str{};
5521
5522 public:
5523 explicit iteration_proxy_value() = default;
5524 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5525 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5526 && std::is_nothrow_default_constructible<string_type>::value)
5527 : anchor(std::move(it))
5528 , array_index(array_index_)
5529 {}
5530
5533 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5535 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5536 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5538 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5539 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5541
5543 const iteration_proxy_value& operator*() const
5544 {
5545 return *this;
5546 }
5547
5550 {
5551 ++anchor;
5552 ++array_index;
5553
5554 return *this;
5555 }
5556
5557 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5558 {
5559 auto tmp = iteration_proxy_value(anchor, array_index);
5560 ++anchor;
5561 ++array_index;
5562 return tmp;
5563 }
5564
5567 {
5568 return anchor == o.anchor;
5569 }
5570
5573 {
5574 return anchor != o.anchor;
5575 }
5576
5578 const string_type& key() const
5579 {
5580 JSON_ASSERT(anchor.m_object != nullptr);
5581
5582 switch (anchor.m_object->type())
5583 {
5584 // use integer array index as key
5585 case value_t::array:
5586 {
5587 if (array_index != array_index_last)
5588 {
5589 int_to_string( array_index_str, array_index );
5590 array_index_last = array_index;
5591 }
5592 return array_index_str;
5593 }
5594
5595 // use key from the object
5596 case value_t::object:
5597 return anchor.key();
5598
5599 // use an empty key for all primitive types
5600 case value_t::null:
5601 case value_t::string:
5602 case value_t::boolean:
5606 case value_t::binary:
5607 case value_t::discarded:
5608 default:
5609 return empty_str;
5610 }
5611 }
5612
5614 typename IteratorType::reference value() const
5615 {
5616 return anchor.value();
5617 }
5618};
5619
5621template<typename IteratorType> class iteration_proxy
5622{
5623 private:
5625 typename IteratorType::pointer container = nullptr;
5626
5627 public:
5628 explicit iteration_proxy() = default;
5629
5631 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5632 : container(&cont) {}
5633
5636 iteration_proxy(iteration_proxy&&) noexcept = default;
5637 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5638 ~iteration_proxy() = default;
5639
5641 iteration_proxy_value<IteratorType> begin() const noexcept
5642 {
5643 return iteration_proxy_value<IteratorType>(container->begin());
5644 }
5645
5648 {
5649 return iteration_proxy_value<IteratorType>(container->end());
5650 }
5651};
5652
5653// Structured Bindings Support
5654// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5655// And see https://github.com/nlohmann/json/pull/1391
5656template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5657auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5658{
5659 return i.key();
5660}
5661// Structured Bindings Support
5662// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5663// And see https://github.com/nlohmann/json/pull/1391
5664template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5665auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5666{
5667 return i.value();
5668}
5669
5670} // namespace detail
5672
5673// The Addition to the STD Namespace is required to add
5674// Structured Bindings Support to the iteration_proxy_value class
5675// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5676// And see https://github.com/nlohmann/json/pull/1391
5677namespace std
5678{
5679
5680#if defined(__clang__)
5681 // Fix: https://github.com/nlohmann/json/issues/1401
5682 #pragma clang diagnostic push
5683 #pragma clang diagnostic ignored "-Wmismatched-tags"
5684#endif
5685template<typename IteratorType>
5686class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5687 : public std::integral_constant<std::size_t, 2> {};
5688
5689template<std::size_t N, typename IteratorType>
5690class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5691{
5692 public:
5693 using type = decltype(
5694 get<N>(std::declval <
5695 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5696};
5697#if defined(__clang__)
5698 #pragma clang diagnostic pop
5699#endif
5700
5701} // namespace std
5702
5703#if JSON_HAS_RANGES
5704 template <typename IteratorType>
5705 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5706#endif
5707
5708// #include <nlohmann/detail/meta/cpp_future.hpp>
5709
5710// #include <nlohmann/detail/meta/std_fs.hpp>
5711
5712// #include <nlohmann/detail/meta/type_traits.hpp>
5713
5714// #include <nlohmann/detail/value_t.hpp>
5715
5716
5718namespace detail
5719{
5720
5722// constructors //
5724
5725/*
5726 * Note all external_constructor<>::construct functions need to call
5727 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5728 * allocated value (e.g., a string). See bug issue
5729 * https://github.com/nlohmann/json/issues/2865 for more information.
5730 */
5731
5732template<value_t> struct external_constructor;
5733
5734template<>
5736{
5737 template<typename BasicJsonType>
5738 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5739 {
5740 j.m_data.m_value.destroy(j.m_data.m_type);
5741 j.m_data.m_type = value_t::boolean;
5742 j.m_data.m_value = b;
5743 j.assert_invariant();
5744 }
5745};
5746
5747template<>
5749{
5750 template<typename BasicJsonType>
5751 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5752 {
5753 j.m_data.m_value.destroy(j.m_data.m_type);
5754 j.m_data.m_type = value_t::string;
5755 j.m_data.m_value = s;
5756 j.assert_invariant();
5757 }
5758
5759 template<typename BasicJsonType>
5760 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5761 {
5762 j.m_data.m_value.destroy(j.m_data.m_type);
5763 j.m_data.m_type = value_t::string;
5764 j.m_data.m_value = std::move(s);
5765 j.assert_invariant();
5766 }
5767
5768 template < typename BasicJsonType, typename CompatibleStringType,
5769 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5770 int > = 0 >
5771 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5772 {
5773 j.m_data.m_value.destroy(j.m_data.m_type);
5774 j.m_data.m_type = value_t::string;
5775 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5776 j.assert_invariant();
5777 }
5778};
5779
5780template<>
5782{
5783 template<typename BasicJsonType>
5784 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5785 {
5786 j.m_data.m_value.destroy(j.m_data.m_type);
5787 j.m_data.m_type = value_t::binary;
5788 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5789 j.assert_invariant();
5790 }
5791
5792 template<typename BasicJsonType>
5793 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5794 {
5795 j.m_data.m_value.destroy(j.m_data.m_type);
5796 j.m_data.m_type = value_t::binary;
5797 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5798 j.assert_invariant();
5799 }
5800};
5801
5802template<>
5804{
5805 template<typename BasicJsonType>
5806 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5807 {
5808 j.m_data.m_value.destroy(j.m_data.m_type);
5809 j.m_data.m_type = value_t::number_float;
5810 j.m_data.m_value = val;
5811 j.assert_invariant();
5812 }
5813};
5814
5815template<>
5817{
5818 template<typename BasicJsonType>
5819 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5820 {
5821 j.m_data.m_value.destroy(j.m_data.m_type);
5822 j.m_data.m_type = value_t::number_unsigned;
5823 j.m_data.m_value = val;
5824 j.assert_invariant();
5825 }
5826};
5827
5828template<>
5830{
5831 template<typename BasicJsonType>
5832 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5833 {
5834 j.m_data.m_value.destroy(j.m_data.m_type);
5835 j.m_data.m_type = value_t::number_integer;
5836 j.m_data.m_value = val;
5837 j.assert_invariant();
5838 }
5839};
5840
5841template<>
5843{
5844 template<typename BasicJsonType>
5845 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5846 {
5847 j.m_data.m_value.destroy(j.m_data.m_type);
5848 j.m_data.m_type = value_t::array;
5849 j.m_data.m_value = arr;
5850 j.set_parents();
5851 j.assert_invariant();
5852 }
5853
5854 template<typename BasicJsonType>
5855 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5856 {
5857 j.m_data.m_value.destroy(j.m_data.m_type);
5858 j.m_data.m_type = value_t::array;
5859 j.m_data.m_value = std::move(arr);
5860 j.set_parents();
5861 j.assert_invariant();
5862 }
5863
5864 template < typename BasicJsonType, typename CompatibleArrayType,
5865 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5866 int > = 0 >
5867 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5868 {
5869 using std::begin;
5870 using std::end;
5871
5872 j.m_data.m_value.destroy(j.m_data.m_type);
5873 j.m_data.m_type = value_t::array;
5874 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5875 j.set_parents();
5876 j.assert_invariant();
5877 }
5878
5879 template<typename BasicJsonType>
5880 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5881 {
5882 j.m_data.m_value.destroy(j.m_data.m_type);
5883 j.m_data.m_type = value_t::array;
5884 j.m_data.m_value = value_t::array;
5885 j.m_data.m_value.array->reserve(arr.size());
5886 for (const bool x : arr)
5887 {
5888 j.m_data.m_value.array->push_back(x);
5889 j.set_parent(j.m_data.m_value.array->back());
5890 }
5891 j.assert_invariant();
5892 }
5893
5894 template<typename BasicJsonType, typename T,
5896 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5897 {
5898 j.m_data.m_value.destroy(j.m_data.m_type);
5899 j.m_data.m_type = value_t::array;
5900 j.m_data.m_value = value_t::array;
5901 j.m_data.m_value.array->resize(arr.size());
5902 if (arr.size() > 0)
5903 {
5904 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5905 }
5906 j.set_parents();
5907 j.assert_invariant();
5908 }
5909};
5910
5911template<>
5913{
5914 template<typename BasicJsonType>
5915 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5916 {
5917 j.m_data.m_value.destroy(j.m_data.m_type);
5918 j.m_data.m_type = value_t::object;
5919 j.m_data.m_value = obj;
5920 j.set_parents();
5921 j.assert_invariant();
5922 }
5923
5924 template<typename BasicJsonType>
5925 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5926 {
5927 j.m_data.m_value.destroy(j.m_data.m_type);
5928 j.m_data.m_type = value_t::object;
5929 j.m_data.m_value = std::move(obj);
5930 j.set_parents();
5931 j.assert_invariant();
5932 }
5933
5934 template < typename BasicJsonType, typename CompatibleObjectType,
5935 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5936 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5937 {
5938 using std::begin;
5939 using std::end;
5940
5941 j.m_data.m_value.destroy(j.m_data.m_type);
5942 j.m_data.m_type = value_t::object;
5943 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5944 j.set_parents();
5945 j.assert_invariant();
5946 }
5947};
5948
5950// to_json //
5952
5953#ifdef JSON_HAS_CPP_17
5954template<typename BasicJsonType, typename T,
5955 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5956void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
5957{
5958 if (opt.has_value())
5959 {
5960 j = *opt;
5961 }
5962 else
5963 {
5964 j = nullptr;
5965 }
5966}
5967#endif
5968
5969template<typename BasicJsonType, typename T,
5971inline void to_json(BasicJsonType& j, T b) noexcept
5972{
5974}
5975
5976template < typename BasicJsonType, typename BoolRef,
5977 enable_if_t <
5978 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5979 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5980 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5981 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5982 typename BasicJsonType::boolean_t >::value))
5983 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5984inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5985{
5986 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5987}
5988
5989template<typename BasicJsonType, typename CompatibleString,
5990 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5991inline void to_json(BasicJsonType& j, const CompatibleString& s)
5992{
5994}
5995
5996template<typename BasicJsonType>
5997inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5998{
6000}
6001
6002template<typename BasicJsonType, typename FloatType,
6003 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
6004inline void to_json(BasicJsonType& j, FloatType val) noexcept
6005{
6006 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
6007}
6008
6009template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
6010 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
6011inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
6012{
6013 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
6014}
6015
6016template<typename BasicJsonType, typename CompatibleNumberIntegerType,
6017 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
6018inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
6019{
6020 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
6021}
6022
6023#if !JSON_DISABLE_ENUM_SERIALIZATION
6024template<typename BasicJsonType, typename EnumType,
6025 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
6026inline void to_json(BasicJsonType& j, EnumType e) noexcept
6027{
6028 using underlying_type = typename std::underlying_type<EnumType>::type;
6029 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
6030 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
6031}
6032#endif // JSON_DISABLE_ENUM_SERIALIZATION
6033
6034template<typename BasicJsonType>
6035inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
6036{
6038}
6039
6040template < typename BasicJsonType, typename CompatibleArrayType,
6041 enable_if_t < is_compatible_array_type<BasicJsonType,
6042 CompatibleArrayType>::value&&
6043 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
6045 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
6046 !is_basic_json<CompatibleArrayType>::value,
6047 int > = 0 >
6048inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
6049{
6051}
6052
6053template<typename BasicJsonType>
6054inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
6055{
6057}
6058
6059template<typename BasicJsonType, typename T,
6060 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
6061inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
6062{
6064}
6065
6066template<typename BasicJsonType>
6067inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
6068{
6070}
6071
6072template < typename BasicJsonType, typename CompatibleObjectType,
6073 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
6074inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
6075{
6077}
6078
6079template<typename BasicJsonType>
6080inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
6081{
6083}
6084
6085template <
6086 typename BasicJsonType, typename T, std::size_t N,
6087 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
6088 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6089 int > = 0 >
6090inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6091{
6093}
6094
6095template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
6096inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
6097{
6098 j = { p.first, p.second };
6099}
6100
6101// for https://github.com/nlohmann/json/pull/1134
6102template<typename BasicJsonType, typename T,
6104inline void to_json(BasicJsonType& j, const T& b)
6105{
6106 j = { {b.key(), b.value()} };
6107}
6108
6109template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
6110inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
6111{
6112 j = { std::get<Idx>(t)... };
6113}
6114
6115template<typename BasicJsonType, typename Tuple>
6116inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
6117{
6118 using array_t = typename BasicJsonType::array_t;
6119 j = array_t();
6120}
6121
6122template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
6123inline void to_json(BasicJsonType& j, const T& t)
6124{
6125 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
6126}
6127
6128#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
6129#if defined(__cpp_lib_char8_t)
6130template<typename BasicJsonType, typename Tr, typename Allocator>
6131inline void to_json(BasicJsonType& j, const std::basic_string<char8_t, Tr, Allocator>& s)
6132{
6133 using OtherAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
6134 j = std::basic_string<char, std::char_traits<char>, OtherAllocator>(s.begin(), s.end(), s.get_allocator());
6135}
6136#endif
6137
6138template<typename BasicJsonType>
6139inline void to_json(BasicJsonType& j, const std_fs::path& p)
6140{
6141 // Returns either a std::string or a std::u8string depending whether library
6142 // support for char8_t is enabled.
6143 j = p.u8string();
6144}
6145#endif
6146
6148{
6149 template<typename BasicJsonType, typename T>
6150 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
6151 -> decltype(to_json(j, std::forward<T>(val)), void())
6152 {
6153 return to_json(j, std::forward<T>(val));
6154 }
6155};
6156} // namespace detail
6157
6158#ifndef JSON_HAS_CPP_17
6162namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
6163{
6164#endif
6165JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
6167#ifndef JSON_HAS_CPP_17
6168} // namespace
6169#endif
6170
6172
6173// #include <nlohmann/detail/meta/identity_tag.hpp>
6174
6175
6177
6179template<typename ValueType, typename>
6181{
6184 template<typename BasicJsonType, typename TargetType = ValueType>
6185 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
6186 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
6187 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
6188 {
6189 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
6190 }
6191
6194 template<typename BasicJsonType, typename TargetType = ValueType>
6195 static auto from_json(BasicJsonType && j) noexcept(
6196 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
6197 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
6198 {
6199 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
6200 }
6201
6204 template<typename BasicJsonType, typename TargetType = ValueType>
6205 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
6206 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
6207 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
6208 {
6209 ::nlohmann::to_json(j, std::forward<TargetType>(val));
6210 }
6211};
6212
6214
6215// #include <nlohmann/byte_container_with_subtype.hpp>
6216// __ _____ _____ _____
6217// __| | __| | | | JSON for Modern C++
6218// | | |__ | | | | | | version 3.12.0
6219// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6220//
6221// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6222// SPDX-License-Identifier: MIT
6223
6224
6225
6226#include <cstdint> // uint8_t, uint64_t
6227#include <tuple> // tie
6228#include <utility> // move
6229
6230// #include <nlohmann/detail/abi_macros.hpp>
6231
6232
6234
6237template<typename BinaryType>
6238class byte_container_with_subtype : public BinaryType
6239{
6240 public:
6241 using container_type = BinaryType;
6242 using subtype_type = std::uint64_t;
6243
6246 : container_type()
6247 {}
6248
6251 : container_type(b)
6252 {}
6253
6255 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
6256 : container_type(std::move(b))
6257 {}
6258
6261 : container_type(b)
6262 , m_subtype(subtype_)
6263 , m_has_subtype(true)
6264 {}
6265
6267 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6268 : container_type(std::move(b))
6269 , m_subtype(subtype_)
6270 , m_has_subtype(true)
6271 {}
6272
6274 {
6275 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6276 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6277 }
6278
6280 {
6281 return !(rhs == *this);
6282 }
6283
6286 void set_subtype(subtype_type subtype_) noexcept
6287 {
6288 m_subtype = subtype_;
6289 m_has_subtype = true;
6290 }
6291
6294 constexpr subtype_type subtype() const noexcept
6295 {
6296 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6297 }
6298
6301 constexpr bool has_subtype() const noexcept
6302 {
6303 return m_has_subtype;
6304 }
6305
6308 void clear_subtype() noexcept
6309 {
6310 m_subtype = 0;
6311 m_has_subtype = false;
6312 }
6313
6314 private:
6315 subtype_type m_subtype = 0;
6316 bool m_has_subtype = false;
6317};
6318
6320
6321// #include <nlohmann/detail/conversions/from_json.hpp>
6322
6323// #include <nlohmann/detail/conversions/to_json.hpp>
6324
6325// #include <nlohmann/detail/exceptions.hpp>
6326
6327// #include <nlohmann/detail/hash.hpp>
6328// __ _____ _____ _____
6329// __| | __| | | | JSON for Modern C++
6330// | | |__ | | | | | | version 3.12.0
6331// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6332//
6333// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6334// SPDX-License-Identifier: MIT
6335
6336
6337
6338#include <cstdint> // uint8_t
6339#include <cstddef> // size_t
6340#include <functional> // hash
6341
6342// #include <nlohmann/detail/abi_macros.hpp>
6343
6344// #include <nlohmann/detail/value_t.hpp>
6345
6346
6348namespace detail
6349{
6350
6351// boost::hash_combine
6352inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6353{
6354 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6355 return seed;
6356}
6357
6369template<typename BasicJsonType>
6370std::size_t hash(const BasicJsonType& j)
6371{
6372 using string_t = typename BasicJsonType::string_t;
6373 using number_integer_t = typename BasicJsonType::number_integer_t;
6374 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6375 using number_float_t = typename BasicJsonType::number_float_t;
6376
6377 const auto type = static_cast<std::size_t>(j.type());
6378 switch (j.type())
6379 {
6380 case BasicJsonType::value_t::null:
6381 case BasicJsonType::value_t::discarded:
6382 {
6383 return combine(type, 0);
6384 }
6385
6386 case BasicJsonType::value_t::object:
6387 {
6388 auto seed = combine(type, j.size());
6389 for (const auto& element : j.items())
6390 {
6391 const auto h = std::hash<string_t> {}(element.key());
6392 seed = combine(seed, h);
6393 seed = combine(seed, hash(element.value()));
6394 }
6395 return seed;
6396 }
6397
6398 case BasicJsonType::value_t::array:
6399 {
6400 auto seed = combine(type, j.size());
6401 for (const auto& element : j)
6402 {
6403 seed = combine(seed, hash(element));
6404 }
6405 return seed;
6406 }
6407
6408 case BasicJsonType::value_t::string:
6409 {
6410 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6411 return combine(type, h);
6412 }
6413
6414 case BasicJsonType::value_t::boolean:
6415 {
6416 const auto h = std::hash<bool> {}(j.template get<bool>());
6417 return combine(type, h);
6418 }
6419
6420 case BasicJsonType::value_t::number_integer:
6421 {
6422 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6423 return combine(type, h);
6424 }
6425
6426 case BasicJsonType::value_t::number_unsigned:
6427 {
6428 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6429 return combine(type, h);
6430 }
6431
6432 case BasicJsonType::value_t::number_float:
6433 {
6434 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6435 return combine(type, h);
6436 }
6437
6438 case BasicJsonType::value_t::binary:
6439 {
6440 auto seed = combine(type, j.get_binary().size());
6441 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6442 seed = combine(seed, h);
6443 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6444 for (const auto byte : j.get_binary())
6445 {
6446 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6447 }
6448 return seed;
6449 }
6450
6451 default: // LCOV_EXCL_LINE
6452 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6453 return 0; // LCOV_EXCL_LINE
6454 }
6455}
6456
6457} // namespace detail
6459
6460// #include <nlohmann/detail/input/binary_reader.hpp>
6461// __ _____ _____ _____
6462// __| | __| | | | JSON for Modern C++
6463// | | |__ | | | | | | version 3.12.0
6464// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6465//
6466// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6467// SPDX-License-Identifier: MIT
6468
6469
6470
6471#include <algorithm> // generate_n
6472#include <array> // array
6473#include <cmath> // ldexp
6474#include <cstddef> // size_t
6475#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6476#include <cstdio> // snprintf
6477#include <cstring> // memcpy
6478#include <iterator> // back_inserter
6479#include <limits> // numeric_limits
6480#include <string> // char_traits, string
6481#include <utility> // make_pair, move
6482#include <vector> // vector
6483#ifdef __cpp_lib_byteswap
6484 #include <bit> //byteswap
6485#endif
6486
6487// #include <nlohmann/detail/exceptions.hpp>
6488
6489// #include <nlohmann/detail/input/input_adapters.hpp>
6490// __ _____ _____ _____
6491// __| | __| | | | JSON for Modern C++
6492// | | |__ | | | | | | version 3.12.0
6493// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6494//
6495// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6496// SPDX-License-Identifier: MIT
6497
6498
6499
6500#include <array> // array
6501#include <cstddef> // size_t
6502#include <cstring> // strlen
6503#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6504#include <memory> // shared_ptr, make_shared, addressof
6505#include <numeric> // accumulate
6506#include <streambuf> // streambuf
6507#include <string> // string, char_traits
6508#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6509#include <utility> // pair, declval
6510
6511#ifndef JSON_NO_IO
6512 #include <cstdio> // FILE *
6513 #include <istream> // istream
6514#endif // JSON_NO_IO
6515
6516// #include <nlohmann/detail/exceptions.hpp>
6517
6518// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6519
6520// #include <nlohmann/detail/macro_scope.hpp>
6521
6522// #include <nlohmann/detail/meta/type_traits.hpp>
6523
6524
6526namespace detail
6527{
6528
6531
6533// input adapters //
6535
6536#ifndef JSON_NO_IO
6542{
6543 public:
6544 using char_type = char;
6545
6547 explicit file_input_adapter(std::FILE* f) noexcept
6548 : m_file(f)
6549 {
6550 JSON_ASSERT(m_file != nullptr);
6551 }
6552
6553 // make class move-only
6556 file_input_adapter& operator=(const file_input_adapter&) = delete;
6559
6560 std::char_traits<char>::int_type get_character() noexcept
6561 {
6562 return std::fgetc(m_file);
6563 }
6564
6565 // returns the number of characters successfully read
6566 template<class T>
6567 std::size_t get_elements(T* dest, std::size_t count = 1)
6568 {
6569 return fread(dest, 1, sizeof(T) * count, m_file);
6570 }
6571
6572 private:
6574 std::FILE* m_file;
6575};
6576
6587{
6588 public:
6589 using char_type = char;
6590
6592 {
6593 // clear stream flags; we use underlying streambuf I/O, do not
6594 // maintain ifstream flags, except eof
6595 if (is != nullptr)
6596 {
6597 is->clear(is->rdstate() & std::ios::eofbit);
6598 }
6599 }
6600
6601 explicit input_stream_adapter(std::istream& i)
6602 : is(&i), sb(i.rdbuf())
6603 {}
6604
6605 // deleted because of pointer members
6609
6611 : is(rhs.is), sb(rhs.sb)
6612 {
6613 rhs.is = nullptr;
6614 rhs.sb = nullptr;
6615 }
6616
6617 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6618 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6619 // end up as the same value, e.g., 0xFFFFFFFF.
6620 std::char_traits<char>::int_type get_character()
6621 {
6622 auto res = sb->sbumpc();
6623 // set eof manually, as we don't use the istream interface.
6624 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6625 {
6626 is->clear(is->rdstate() | std::ios::eofbit);
6627 }
6628 return res;
6629 }
6630
6631 template<class T>
6632 std::size_t get_elements(T* dest, std::size_t count = 1)
6633 {
6634 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6635 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
6636 {
6637 is->clear(is->rdstate() | std::ios::eofbit);
6638 }
6639 return res;
6640 }
6641
6642 private:
6644 std::istream* is = nullptr;
6645 std::streambuf* sb = nullptr;
6646};
6647#endif // JSON_NO_IO
6648
6649// General-purpose iterator-based adapter. It might not be as fast as
6650// theoretically possible for some containers, but it is extremely versatile.
6651template<typename IteratorType>
6653{
6654 public:
6655 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6656
6657 iterator_input_adapter(IteratorType first, IteratorType last)
6658 : current(std::move(first)), end(std::move(last))
6659 {}
6660
6662 {
6663 if (JSON_HEDLEY_LIKELY(current != end))
6664 {
6665 auto result = char_traits<char_type>::to_int_type(*current);
6666 std::advance(current, 1);
6667 return result;
6668 }
6669
6671 }
6672
6673 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6674 template<class T>
6675 std::size_t get_elements(T* dest, std::size_t count = 1)
6676 {
6677 auto* ptr = reinterpret_cast<char*>(dest);
6678 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
6679 {
6680 if (JSON_HEDLEY_LIKELY(current != end))
6681 {
6682 ptr[read_index] = static_cast<char>(*current);
6683 std::advance(current, 1);
6684 }
6685 else
6686 {
6687 return read_index;
6688 }
6689 }
6690 return count * sizeof(T);
6691 }
6692
6693 private:
6694 IteratorType current;
6695 IteratorType end;
6696
6697 template<typename BaseInputAdapter, size_t T>
6699
6700 bool empty() const
6701 {
6702 return current == end;
6703 }
6704};
6705
6706template<typename BaseInputAdapter, size_t T>
6708
6709template<typename BaseInputAdapter>
6710struct wide_string_input_helper<BaseInputAdapter, 4>
6711{
6712 // UTF-32
6713 static void fill_buffer(BaseInputAdapter& input,
6714 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6715 size_t& utf8_bytes_index,
6716 size_t& utf8_bytes_filled)
6717 {
6718 utf8_bytes_index = 0;
6719
6720 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6721 {
6722 utf8_bytes[0] = std::char_traits<char>::eof();
6723 utf8_bytes_filled = 1;
6724 }
6725 else
6726 {
6727 // get the current character
6728 const auto wc = input.get_character();
6729
6730 // UTF-32 to UTF-8 encoding
6731 if (wc < 0x80)
6732 {
6733 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6734 utf8_bytes_filled = 1;
6735 }
6736 else if (wc <= 0x7FF)
6737 {
6738 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6739 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6740 utf8_bytes_filled = 2;
6741 }
6742 else if (wc <= 0xFFFF)
6743 {
6744 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6745 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6746 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6747 utf8_bytes_filled = 3;
6748 }
6749 else if (wc <= 0x10FFFF)
6750 {
6751 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6752 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6753 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6754 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6755 utf8_bytes_filled = 4;
6756 }
6757 else
6758 {
6759 // unknown character
6760 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6761 utf8_bytes_filled = 1;
6762 }
6763 }
6764 }
6765};
6766
6767template<typename BaseInputAdapter>
6768struct wide_string_input_helper<BaseInputAdapter, 2>
6769{
6770 // UTF-16
6771 static void fill_buffer(BaseInputAdapter& input,
6772 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6773 size_t& utf8_bytes_index,
6774 size_t& utf8_bytes_filled)
6775 {
6776 utf8_bytes_index = 0;
6777
6778 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6779 {
6780 utf8_bytes[0] = std::char_traits<char>::eof();
6781 utf8_bytes_filled = 1;
6782 }
6783 else
6784 {
6785 // get the current character
6786 const auto wc = input.get_character();
6787
6788 // UTF-16 to UTF-8 encoding
6789 if (wc < 0x80)
6790 {
6791 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6792 utf8_bytes_filled = 1;
6793 }
6794 else if (wc <= 0x7FF)
6795 {
6796 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6797 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6798 utf8_bytes_filled = 2;
6799 }
6800 else if (0xD800 > wc || wc >= 0xE000)
6801 {
6802 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6803 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6804 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6805 utf8_bytes_filled = 3;
6806 }
6807 else
6808 {
6809 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6810 {
6811 const auto wc2 = static_cast<unsigned int>(input.get_character());
6812 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6813 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6814 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6815 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6816 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6817 utf8_bytes_filled = 4;
6818 }
6819 else
6820 {
6821 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6822 utf8_bytes_filled = 1;
6823 }
6824 }
6825 }
6826 }
6827};
6828
6829// Wraps another input adapter to convert wide character types into individual bytes.
6830template<typename BaseInputAdapter, typename WideCharType>
6832{
6833 public:
6834 using char_type = char;
6835
6836 wide_string_input_adapter(BaseInputAdapter base)
6837 : base_adapter(base) {}
6838
6839 typename std::char_traits<char>::int_type get_character() noexcept
6840 {
6841 // check if the buffer needs to be filled
6842 if (utf8_bytes_index == utf8_bytes_filled)
6843 {
6844 fill_buffer<sizeof(WideCharType)>();
6845
6846 JSON_ASSERT(utf8_bytes_filled > 0);
6847 JSON_ASSERT(utf8_bytes_index == 0);
6848 }
6849
6850 // use buffer
6851 JSON_ASSERT(utf8_bytes_filled > 0);
6852 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6853 return utf8_bytes[utf8_bytes_index++];
6854 }
6855
6856 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6857 template<class T>
6858 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
6859 {
6860 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6861 }
6862
6863 private:
6864 BaseInputAdapter base_adapter;
6865
6866 template<size_t T>
6867 void fill_buffer()
6868 {
6869 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6870 }
6871
6873 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6874
6876 std::size_t utf8_bytes_index = 0;
6878 std::size_t utf8_bytes_filled = 0;
6879};
6880
6881template<typename IteratorType, typename Enable = void>
6883{
6884 using iterator_type = IteratorType;
6885 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6887
6888 static adapter_type create(IteratorType first, IteratorType last)
6889 {
6890 return adapter_type(std::move(first), std::move(last));
6891 }
6892};
6893
6894template<typename T>
6896{
6897 using value_type = typename std::iterator_traits<T>::value_type;
6898 enum
6899 {
6900 value = sizeof(value_type) > 1
6901 };
6902};
6903
6904template<typename IteratorType>
6906{
6907 using iterator_type = IteratorType;
6908 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6911
6912 static adapter_type create(IteratorType first, IteratorType last)
6913 {
6914 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6915 }
6916};
6917
6918// General purpose iterator-based input
6919template<typename IteratorType>
6921{
6923 return factory_type::create(first, last);
6924}
6925
6926// Convenience shorthand from container to iterator
6927// Enables ADL on begin(container) and end(container)
6928// Encloses the using declarations in namespace for not to leak them to outside scope
6929
6931{
6932
6933using std::begin;
6934using std::end;
6935
6936template<typename ContainerType, typename Enable = void>
6938
6939template<typename ContainerType>
6941 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6942 {
6943 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6944
6945 static adapter_type create(const ContainerType& container)
6946{
6947 return input_adapter(begin(container), end(container));
6948}
6949 };
6950
6951} // namespace container_input_adapter_factory_impl
6952
6953template<typename ContainerType>
6958
6959// specialization for std::string
6960using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
6961
6962#ifndef JSON_NO_IO
6963// Special cases with fast paths
6964inline file_input_adapter input_adapter(std::FILE* file)
6965{
6966 if (file == nullptr)
6967 {
6968 JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
6969 }
6970 return file_input_adapter(file);
6971}
6972
6973inline input_stream_adapter input_adapter(std::istream& stream)
6974{
6975 return input_stream_adapter(stream);
6976}
6977
6978inline input_stream_adapter input_adapter(std::istream&& stream)
6979{
6980 return input_stream_adapter(stream);
6981}
6982#endif // JSON_NO_IO
6983
6984using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6985
6986// Null-delimited strings, and the like.
6987template < typename CharT,
6988 typename std::enable_if <
6989 std::is_pointer<CharT>::value&&
6990 !std::is_array<CharT>::value&&
6991 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6992 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6993 int >::type = 0 >
6995{
6996 if (b == nullptr)
6997 {
6998 JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
6999 }
7000 auto length = std::strlen(reinterpret_cast<const char*>(b));
7001 const auto* ptr = reinterpret_cast<const char*>(b);
7002 return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
7003}
7004
7005template<typename T, std::size_t N>
7006auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
7007{
7008 return input_adapter(array, array + N);
7009}
7010
7011// This class only handles inputs of input_buffer_adapter type.
7012// It's required so that expressions like {ptr, len} can be implicitly cast
7013// to the correct adapter.
7015{
7016 public:
7017 template < typename CharT,
7018 typename std::enable_if <
7019 std::is_pointer<CharT>::value&&
7020 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
7021 sizeof(typename std::remove_pointer<CharT>::type) == 1,
7022 int >::type = 0 >
7023 span_input_adapter(CharT b, std::size_t l)
7024 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
7025
7026 template<class IteratorType,
7027 typename std::enable_if<
7028 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
7029 int>::type = 0>
7030 span_input_adapter(IteratorType first, IteratorType last)
7031 : ia(input_adapter(first, last)) {}
7032
7034 {
7035 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
7036 }
7037
7038 private:
7040};
7041
7042} // namespace detail
7044
7045// #include <nlohmann/detail/input/json_sax.hpp>
7046// __ _____ _____ _____
7047// __| | __| | | | JSON for Modern C++
7048// | | |__ | | | | | | version 3.12.0
7049// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7050//
7051// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7052// SPDX-License-Identifier: MIT
7053
7054
7055
7056#include <cstddef>
7057#include <string> // string
7058#include <type_traits> // enable_if_t
7059#include <utility> // move
7060#include <vector> // vector
7061
7062// #include <nlohmann/detail/exceptions.hpp>
7063
7064// #include <nlohmann/detail/input/lexer.hpp>
7065// __ _____ _____ _____
7066// __| | __| | | | JSON for Modern C++
7067// | | |__ | | | | | | version 3.12.0
7068// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7069//
7070// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7071// SPDX-License-Identifier: MIT
7072
7073
7074
7075#include <array> // array
7076#include <clocale> // localeconv
7077#include <cstddef> // size_t
7078#include <cstdio> // snprintf
7079#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7080#include <initializer_list> // initializer_list
7081#include <string> // char_traits, string
7082#include <utility> // move
7083#include <vector> // vector
7084
7085// #include <nlohmann/detail/input/input_adapters.hpp>
7086
7087// #include <nlohmann/detail/input/position_t.hpp>
7088
7089// #include <nlohmann/detail/macro_scope.hpp>
7090
7091// #include <nlohmann/detail/meta/type_traits.hpp>
7092
7093
7095namespace detail
7096{
7097
7099// lexer //
7101
7102template<typename BasicJsonType>
7104{
7105 public:
7127
7131 static const char* token_type_name(const token_type t) noexcept
7132 {
7133 switch (t)
7134 {
7136 return "<uninitialized>";
7138 return "true literal";
7140 return "false literal";
7142 return "null literal";
7144 return "string literal";
7148 return "number literal";
7150 return "'['";
7152 return "'{'";
7154 return "']'";
7156 return "'}'";
7158 return "':'";
7160 return "','";
7162 return "<parse error>";
7164 return "end of input";
7166 return "'[', '{', or a literal";
7167 // LCOV_EXCL_START
7168 default: // catch non-enum values
7169 return "unknown token";
7170 // LCOV_EXCL_STOP
7171 }
7172 }
7173};
7174
7179template<typename BasicJsonType, typename InputAdapterType>
7180class lexer : public lexer_base<BasicJsonType>
7181{
7182 using number_integer_t = typename BasicJsonType::number_integer_t;
7183 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7184 using number_float_t = typename BasicJsonType::number_float_t;
7185 using string_t = typename BasicJsonType::string_t;
7186 using char_type = typename InputAdapterType::char_type;
7187 using char_int_type = typename char_traits<char_type>::int_type;
7188
7189 public:
7191
7192 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7193 : ia(std::move(adapter))
7194 , ignore_comments(ignore_comments_)
7195 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7196 {}
7197
7198 // deleted because of pointer members
7199 lexer(const lexer&) = delete;
7200 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7201 lexer& operator=(lexer&) = delete;
7202 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7203 ~lexer() = default;
7204
7205 private:
7207 // locales
7209
7212 static char get_decimal_point() noexcept
7213 {
7214 const auto* loc = localeconv();
7215 JSON_ASSERT(loc != nullptr);
7216 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7217 }
7218
7220 // scan functions
7222
7238 int get_codepoint()
7239 {
7240 // this function only makes sense after reading `\u`
7241 JSON_ASSERT(current == 'u');
7242 int codepoint = 0;
7243
7244 const auto factors = { 12u, 8u, 4u, 0u };
7245 for (const auto factor : factors)
7246 {
7247 get();
7248
7249 if (current >= '0' && current <= '9')
7250 {
7251 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7252 }
7253 else if (current >= 'A' && current <= 'F')
7254 {
7255 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7256 }
7257 else if (current >= 'a' && current <= 'f')
7258 {
7259 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7260 }
7261 else
7262 {
7263 return -1;
7264 }
7265 }
7266
7267 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7268 return codepoint;
7269 }
7270
7286 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7287 {
7288 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7289 add(current);
7290
7291 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7292 {
7293 get();
7294 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7295 {
7296 add(current);
7297 }
7298 else
7299 {
7300 error_message = "invalid string: ill-formed UTF-8 byte";
7301 return false;
7302 }
7303 }
7304
7305 return true;
7306 }
7307
7323 token_type scan_string()
7324 {
7325 // reset token_buffer (ignore opening quote)
7326 reset();
7327
7328 // we entered the function by reading an open quote
7329 JSON_ASSERT(current == '\"');
7330
7331 while (true)
7332 {
7333 // get the next character
7334 switch (get())
7335 {
7336 // end of file while parsing the string
7337 case char_traits<char_type>::eof():
7338 {
7339 error_message = "invalid string: missing closing quote";
7340 return token_type::parse_error;
7341 }
7342
7343 // closing quote
7344 case '\"':
7345 {
7346 return token_type::value_string;
7347 }
7348
7349 // escapes
7350 case '\\':
7351 {
7352 switch (get())
7353 {
7354 // quotation mark
7355 case '\"':
7356 add('\"');
7357 break;
7358 // reverse solidus
7359 case '\\':
7360 add('\\');
7361 break;
7362 // solidus
7363 case '/':
7364 add('/');
7365 break;
7366 // backspace
7367 case 'b':
7368 add('\b');
7369 break;
7370 // form feed
7371 case 'f':
7372 add('\f');
7373 break;
7374 // line feed
7375 case 'n':
7376 add('\n');
7377 break;
7378 // carriage return
7379 case 'r':
7380 add('\r');
7381 break;
7382 // tab
7383 case 't':
7384 add('\t');
7385 break;
7386
7387 // unicode escapes
7388 case 'u':
7389 {
7390 const int codepoint1 = get_codepoint();
7391 int codepoint = codepoint1; // start with codepoint1
7392
7393 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7394 {
7395 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7396 return token_type::parse_error;
7397 }
7398
7399 // check if code point is a high surrogate
7400 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7401 {
7402 // expect next \uxxxx entry
7403 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7404 {
7405 const int codepoint2 = get_codepoint();
7406
7407 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7408 {
7409 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7410 return token_type::parse_error;
7411 }
7412
7413 // check if codepoint2 is a low surrogate
7414 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7415 {
7416 // overwrite codepoint
7417 codepoint = static_cast<int>(
7418 // high surrogate occupies the most significant 22 bits
7419 (static_cast<unsigned int>(codepoint1) << 10u)
7420 // low surrogate occupies the least significant 15 bits
7421 + static_cast<unsigned int>(codepoint2)
7422 // there is still the 0xD800, 0xDC00, and 0x10000 noise
7423 // in the result, so we have to subtract with:
7424 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7425 - 0x35FDC00u);
7426 }
7427 else
7428 {
7429 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7430 return token_type::parse_error;
7431 }
7432 }
7433 else
7434 {
7435 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7436 return token_type::parse_error;
7437 }
7438 }
7439 else
7440 {
7441 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7442 {
7443 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7444 return token_type::parse_error;
7445 }
7446 }
7447
7448 // the result of the above calculation yields a proper codepoint
7449 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7450
7451 // translate codepoint into bytes
7452 if (codepoint < 0x80)
7453 {
7454 // 1-byte characters: 0xxxxxxx (ASCII)
7455 add(static_cast<char_int_type>(codepoint));
7456 }
7457 else if (codepoint <= 0x7FF)
7458 {
7459 // 2-byte characters: 110xxxxx 10xxxxxx
7460 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7461 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7462 }
7463 else if (codepoint <= 0xFFFF)
7464 {
7465 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7466 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7467 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7468 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7469 }
7470 else
7471 {
7472 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7473 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7474 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7475 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7476 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7477 }
7478
7479 break;
7480 }
7481
7482 // other characters after escape
7483 default:
7484 error_message = "invalid string: forbidden character after backslash";
7485 return token_type::parse_error;
7486 }
7487
7488 break;
7489 }
7490
7491 // invalid control characters
7492 case 0x00:
7493 {
7494 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7495 return token_type::parse_error;
7496 }
7497
7498 case 0x01:
7499 {
7500 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7501 return token_type::parse_error;
7502 }
7503
7504 case 0x02:
7505 {
7506 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7507 return token_type::parse_error;
7508 }
7509
7510 case 0x03:
7511 {
7512 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7513 return token_type::parse_error;
7514 }
7515
7516 case 0x04:
7517 {
7518 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7519 return token_type::parse_error;
7520 }
7521
7522 case 0x05:
7523 {
7524 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7525 return token_type::parse_error;
7526 }
7527
7528 case 0x06:
7529 {
7530 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7531 return token_type::parse_error;
7532 }
7533
7534 case 0x07:
7535 {
7536 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7537 return token_type::parse_error;
7538 }
7539
7540 case 0x08:
7541 {
7542 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7543 return token_type::parse_error;
7544 }
7545
7546 case 0x09:
7547 {
7548 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7549 return token_type::parse_error;
7550 }
7551
7552 case 0x0A:
7553 {
7554 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7555 return token_type::parse_error;
7556 }
7557
7558 case 0x0B:
7559 {
7560 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7561 return token_type::parse_error;
7562 }
7563
7564 case 0x0C:
7565 {
7566 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7567 return token_type::parse_error;
7568 }
7569
7570 case 0x0D:
7571 {
7572 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7573 return token_type::parse_error;
7574 }
7575
7576 case 0x0E:
7577 {
7578 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7579 return token_type::parse_error;
7580 }
7581
7582 case 0x0F:
7583 {
7584 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7585 return token_type::parse_error;
7586 }
7587
7588 case 0x10:
7589 {
7590 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7591 return token_type::parse_error;
7592 }
7593
7594 case 0x11:
7595 {
7596 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7597 return token_type::parse_error;
7598 }
7599
7600 case 0x12:
7601 {
7602 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7603 return token_type::parse_error;
7604 }
7605
7606 case 0x13:
7607 {
7608 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7609 return token_type::parse_error;
7610 }
7611
7612 case 0x14:
7613 {
7614 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7615 return token_type::parse_error;
7616 }
7617
7618 case 0x15:
7619 {
7620 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7621 return token_type::parse_error;
7622 }
7623
7624 case 0x16:
7625 {
7626 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7627 return token_type::parse_error;
7628 }
7629
7630 case 0x17:
7631 {
7632 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7633 return token_type::parse_error;
7634 }
7635
7636 case 0x18:
7637 {
7638 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7639 return token_type::parse_error;
7640 }
7641
7642 case 0x19:
7643 {
7644 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7645 return token_type::parse_error;
7646 }
7647
7648 case 0x1A:
7649 {
7650 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7651 return token_type::parse_error;
7652 }
7653
7654 case 0x1B:
7655 {
7656 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7657 return token_type::parse_error;
7658 }
7659
7660 case 0x1C:
7661 {
7662 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7663 return token_type::parse_error;
7664 }
7665
7666 case 0x1D:
7667 {
7668 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7669 return token_type::parse_error;
7670 }
7671
7672 case 0x1E:
7673 {
7674 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7675 return token_type::parse_error;
7676 }
7677
7678 case 0x1F:
7679 {
7680 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7681 return token_type::parse_error;
7682 }
7683
7684 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7685 case 0x20:
7686 case 0x21:
7687 case 0x23:
7688 case 0x24:
7689 case 0x25:
7690 case 0x26:
7691 case 0x27:
7692 case 0x28:
7693 case 0x29:
7694 case 0x2A:
7695 case 0x2B:
7696 case 0x2C:
7697 case 0x2D:
7698 case 0x2E:
7699 case 0x2F:
7700 case 0x30:
7701 case 0x31:
7702 case 0x32:
7703 case 0x33:
7704 case 0x34:
7705 case 0x35:
7706 case 0x36:
7707 case 0x37:
7708 case 0x38:
7709 case 0x39:
7710 case 0x3A:
7711 case 0x3B:
7712 case 0x3C:
7713 case 0x3D:
7714 case 0x3E:
7715 case 0x3F:
7716 case 0x40:
7717 case 0x41:
7718 case 0x42:
7719 case 0x43:
7720 case 0x44:
7721 case 0x45:
7722 case 0x46:
7723 case 0x47:
7724 case 0x48:
7725 case 0x49:
7726 case 0x4A:
7727 case 0x4B:
7728 case 0x4C:
7729 case 0x4D:
7730 case 0x4E:
7731 case 0x4F:
7732 case 0x50:
7733 case 0x51:
7734 case 0x52:
7735 case 0x53:
7736 case 0x54:
7737 case 0x55:
7738 case 0x56:
7739 case 0x57:
7740 case 0x58:
7741 case 0x59:
7742 case 0x5A:
7743 case 0x5B:
7744 case 0x5D:
7745 case 0x5E:
7746 case 0x5F:
7747 case 0x60:
7748 case 0x61:
7749 case 0x62:
7750 case 0x63:
7751 case 0x64:
7752 case 0x65:
7753 case 0x66:
7754 case 0x67:
7755 case 0x68:
7756 case 0x69:
7757 case 0x6A:
7758 case 0x6B:
7759 case 0x6C:
7760 case 0x6D:
7761 case 0x6E:
7762 case 0x6F:
7763 case 0x70:
7764 case 0x71:
7765 case 0x72:
7766 case 0x73:
7767 case 0x74:
7768 case 0x75:
7769 case 0x76:
7770 case 0x77:
7771 case 0x78:
7772 case 0x79:
7773 case 0x7A:
7774 case 0x7B:
7775 case 0x7C:
7776 case 0x7D:
7777 case 0x7E:
7778 case 0x7F:
7779 {
7780 add(current);
7781 break;
7782 }
7783
7784 // U+0080..U+07FF: bytes C2..DF 80..BF
7785 case 0xC2:
7786 case 0xC3:
7787 case 0xC4:
7788 case 0xC5:
7789 case 0xC6:
7790 case 0xC7:
7791 case 0xC8:
7792 case 0xC9:
7793 case 0xCA:
7794 case 0xCB:
7795 case 0xCC:
7796 case 0xCD:
7797 case 0xCE:
7798 case 0xCF:
7799 case 0xD0:
7800 case 0xD1:
7801 case 0xD2:
7802 case 0xD3:
7803 case 0xD4:
7804 case 0xD5:
7805 case 0xD6:
7806 case 0xD7:
7807 case 0xD8:
7808 case 0xD9:
7809 case 0xDA:
7810 case 0xDB:
7811 case 0xDC:
7812 case 0xDD:
7813 case 0xDE:
7814 case 0xDF:
7815 {
7816 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7817 {
7818 return token_type::parse_error;
7819 }
7820 break;
7821 }
7822
7823 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7824 case 0xE0:
7825 {
7826 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7827 {
7828 return token_type::parse_error;
7829 }
7830 break;
7831 }
7832
7833 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7834 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7835 case 0xE1:
7836 case 0xE2:
7837 case 0xE3:
7838 case 0xE4:
7839 case 0xE5:
7840 case 0xE6:
7841 case 0xE7:
7842 case 0xE8:
7843 case 0xE9:
7844 case 0xEA:
7845 case 0xEB:
7846 case 0xEC:
7847 case 0xEE:
7848 case 0xEF:
7849 {
7850 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7851 {
7852 return token_type::parse_error;
7853 }
7854 break;
7855 }
7856
7857 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7858 case 0xED:
7859 {
7860 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7861 {
7862 return token_type::parse_error;
7863 }
7864 break;
7865 }
7866
7867 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7868 case 0xF0:
7869 {
7870 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7871 {
7872 return token_type::parse_error;
7873 }
7874 break;
7875 }
7876
7877 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7878 case 0xF1:
7879 case 0xF2:
7880 case 0xF3:
7881 {
7882 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7883 {
7884 return token_type::parse_error;
7885 }
7886 break;
7887 }
7888
7889 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7890 case 0xF4:
7891 {
7892 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7893 {
7894 return token_type::parse_error;
7895 }
7896 break;
7897 }
7898
7899 // the remaining bytes (80..C1 and F5..FF) are ill-formed
7900 default:
7901 {
7902 error_message = "invalid string: ill-formed UTF-8 byte";
7903 return token_type::parse_error;
7904 }
7905 }
7906 }
7907 }
7908
7913 bool scan_comment()
7914 {
7915 switch (get())
7916 {
7917 // single-line comments skip input until a newline or EOF is read
7918 case '/':
7919 {
7920 while (true)
7921 {
7922 switch (get())
7923 {
7924 case '\n':
7925 case '\r':
7927 case '\0':
7928 return true;
7929
7930 default:
7931 break;
7932 }
7933 }
7934 }
7935
7936 // multi-line comments skip input until */ is read
7937 case '*':
7938 {
7939 while (true)
7940 {
7941 switch (get())
7942 {
7944 case '\0':
7945 {
7946 error_message = "invalid comment; missing closing '*/'";
7947 return false;
7948 }
7949
7950 case '*':
7951 {
7952 switch (get())
7953 {
7954 case '/':
7955 return true;
7956
7957 default:
7958 {
7959 unget();
7960 continue;
7961 }
7962 }
7963 }
7964
7965 default:
7966 continue;
7967 }
7968 }
7969 }
7970
7971 // unexpected character after reading '/'
7972 default:
7973 {
7974 error_message = "invalid comment; expecting '/' or '*' after '/'";
7975 return false;
7976 }
7977 }
7978 }
7979
7981 static void strtof(float& f, const char* str, char** endptr) noexcept
7982 {
7983 f = std::strtof(str, endptr);
7984 }
7985
7987 static void strtof(double& f, const char* str, char** endptr) noexcept
7988 {
7989 f = std::strtod(str, endptr);
7990 }
7991
7993 static void strtof(long double& f, const char* str, char** endptr) noexcept
7994 {
7995 f = std::strtold(str, endptr);
7996 }
7997
8038 token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
8039 {
8040 // reset token_buffer to store the number's bytes
8041 reset();
8042
8043 // the type of the parsed number; initially set to unsigned; will be
8044 // changed if minus sign, decimal point, or exponent is read
8045 token_type number_type = token_type::value_unsigned;
8046
8047 // state (init): we just found out we need to scan a number
8048 switch (current)
8049 {
8050 case '-':
8051 {
8052 add(current);
8053 goto scan_number_minus;
8054 }
8055
8056 case '0':
8057 {
8058 add(current);
8059 goto scan_number_zero;
8060 }
8061
8062 case '1':
8063 case '2':
8064 case '3':
8065 case '4':
8066 case '5':
8067 case '6':
8068 case '7':
8069 case '8':
8070 case '9':
8071 {
8072 add(current);
8073 goto scan_number_any1;
8074 }
8075
8076 // all other characters are rejected outside scan_number()
8077 default: // LCOV_EXCL_LINE
8078 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8079 }
8080
8081scan_number_minus:
8082 // state: we just parsed a leading minus sign
8083 number_type = token_type::value_integer;
8084 switch (get())
8085 {
8086 case '0':
8087 {
8088 add(current);
8089 goto scan_number_zero;
8090 }
8091
8092 case '1':
8093 case '2':
8094 case '3':
8095 case '4':
8096 case '5':
8097 case '6':
8098 case '7':
8099 case '8':
8100 case '9':
8101 {
8102 add(current);
8103 goto scan_number_any1;
8104 }
8105
8106 default:
8107 {
8108 error_message = "invalid number; expected digit after '-'";
8109 return token_type::parse_error;
8110 }
8111 }
8112
8113scan_number_zero:
8114 // state: we just parse a zero (maybe with a leading minus sign)
8115 switch (get())
8116 {
8117 case '.':
8118 {
8119 add(decimal_point_char);
8120 decimal_point_position = token_buffer.size() - 1;
8121 goto scan_number_decimal1;
8122 }
8123
8124 case 'e':
8125 case 'E':
8126 {
8127 add(current);
8128 goto scan_number_exponent;
8129 }
8130
8131 default:
8132 goto scan_number_done;
8133 }
8134
8135scan_number_any1:
8136 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8137 switch (get())
8138 {
8139 case '0':
8140 case '1':
8141 case '2':
8142 case '3':
8143 case '4':
8144 case '5':
8145 case '6':
8146 case '7':
8147 case '8':
8148 case '9':
8149 {
8150 add(current);
8151 goto scan_number_any1;
8152 }
8153
8154 case '.':
8155 {
8156 add(decimal_point_char);
8157 decimal_point_position = token_buffer.size() - 1;
8158 goto scan_number_decimal1;
8159 }
8160
8161 case 'e':
8162 case 'E':
8163 {
8164 add(current);
8165 goto scan_number_exponent;
8166 }
8167
8168 default:
8169 goto scan_number_done;
8170 }
8171
8172scan_number_decimal1:
8173 // state: we just parsed a decimal point
8174 number_type = token_type::value_float;
8175 switch (get())
8176 {
8177 case '0':
8178 case '1':
8179 case '2':
8180 case '3':
8181 case '4':
8182 case '5':
8183 case '6':
8184 case '7':
8185 case '8':
8186 case '9':
8187 {
8188 add(current);
8189 goto scan_number_decimal2;
8190 }
8191
8192 default:
8193 {
8194 error_message = "invalid number; expected digit after '.'";
8195 return token_type::parse_error;
8196 }
8197 }
8198
8199scan_number_decimal2:
8200 // we just parsed at least one number after a decimal point
8201 switch (get())
8202 {
8203 case '0':
8204 case '1':
8205 case '2':
8206 case '3':
8207 case '4':
8208 case '5':
8209 case '6':
8210 case '7':
8211 case '8':
8212 case '9':
8213 {
8214 add(current);
8215 goto scan_number_decimal2;
8216 }
8217
8218 case 'e':
8219 case 'E':
8220 {
8221 add(current);
8222 goto scan_number_exponent;
8223 }
8224
8225 default:
8226 goto scan_number_done;
8227 }
8228
8229scan_number_exponent:
8230 // we just parsed an exponent
8231 number_type = token_type::value_float;
8232 switch (get())
8233 {
8234 case '+':
8235 case '-':
8236 {
8237 add(current);
8238 goto scan_number_sign;
8239 }
8240
8241 case '0':
8242 case '1':
8243 case '2':
8244 case '3':
8245 case '4':
8246 case '5':
8247 case '6':
8248 case '7':
8249 case '8':
8250 case '9':
8251 {
8252 add(current);
8253 goto scan_number_any2;
8254 }
8255
8256 default:
8257 {
8258 error_message =
8259 "invalid number; expected '+', '-', or digit after exponent";
8260 return token_type::parse_error;
8261 }
8262 }
8263
8264scan_number_sign:
8265 // we just parsed an exponent sign
8266 switch (get())
8267 {
8268 case '0':
8269 case '1':
8270 case '2':
8271 case '3':
8272 case '4':
8273 case '5':
8274 case '6':
8275 case '7':
8276 case '8':
8277 case '9':
8278 {
8279 add(current);
8280 goto scan_number_any2;
8281 }
8282
8283 default:
8284 {
8285 error_message = "invalid number; expected digit after exponent sign";
8286 return token_type::parse_error;
8287 }
8288 }
8289
8290scan_number_any2:
8291 // we just parsed a number after the exponent or exponent sign
8292 switch (get())
8293 {
8294 case '0':
8295 case '1':
8296 case '2':
8297 case '3':
8298 case '4':
8299 case '5':
8300 case '6':
8301 case '7':
8302 case '8':
8303 case '9':
8304 {
8305 add(current);
8306 goto scan_number_any2;
8307 }
8308
8309 default:
8310 goto scan_number_done;
8311 }
8312
8313scan_number_done:
8314 // unget the character after the number (we only read it to know that
8315 // we are done scanning a number)
8316 unget();
8317
8318 char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8319 errno = 0;
8320
8321 // try to parse integers first and fall back to floats
8322 if (number_type == token_type::value_unsigned)
8323 {
8324 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8325
8326 // we checked the number format before
8327 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8328
8329 if (errno != ERANGE)
8330 {
8331 value_unsigned = static_cast<number_unsigned_t>(x);
8332 if (value_unsigned == x)
8333 {
8334 return token_type::value_unsigned;
8335 }
8336 }
8337 }
8338 else if (number_type == token_type::value_integer)
8339 {
8340 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8341
8342 // we checked the number format before
8343 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8344
8345 if (errno != ERANGE)
8346 {
8347 value_integer = static_cast<number_integer_t>(x);
8348 if (value_integer == x)
8349 {
8350 return token_type::value_integer;
8351 }
8352 }
8353 }
8354
8355 // this code is reached if we parse a floating-point number or if an
8356 // integer conversion above failed
8357 strtof(value_float, token_buffer.data(), &endptr);
8358
8359 // we checked the number format before
8360 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8361
8362 return token_type::value_float;
8363 }
8364
8371 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8372 token_type return_type)
8373 {
8374 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8375 for (std::size_t i = 1; i < length; ++i)
8376 {
8378 {
8379 error_message = "invalid literal";
8380 return token_type::parse_error;
8381 }
8382 }
8383 return return_type;
8384 }
8385
8387 // input management
8389
8391 void reset() noexcept
8392 {
8393 token_buffer.clear();
8394 token_string.clear();
8395 decimal_point_position = std::string::npos;
8396 token_string.push_back(char_traits<char_type>::to_char_type(current));
8397 }
8398
8399 /*
8400 @brief get next character from the input
8401
8402 This function provides the interface to the used input adapter. It does
8403 not throw in case the input reached EOF, but returns a
8404 `char_traits<char>::eof()` in that case. Stores the scanned characters
8405 for use in error messages.
8406
8407 @return character read from the input
8408 */
8409 char_int_type get()
8410 {
8411 ++position.chars_read_total;
8412 ++position.chars_read_current_line;
8413
8414 if (next_unget)
8415 {
8416 // only reset the next_unget variable and work with current
8417 next_unget = false;
8418 }
8419 else
8420 {
8421 current = ia.get_character();
8422 }
8423
8425 {
8426 token_string.push_back(char_traits<char_type>::to_char_type(current));
8427 }
8428
8429 if (current == '\n')
8430 {
8431 ++position.lines_read;
8432 position.chars_read_current_line = 0;
8433 }
8434
8435 return current;
8436 }
8437
8446 void unget()
8447 {
8448 next_unget = true;
8449
8450 --position.chars_read_total;
8451
8452 // in case we "unget" a newline, we have to also decrement the lines_read
8453 if (position.chars_read_current_line == 0)
8454 {
8455 if (position.lines_read > 0)
8456 {
8457 --position.lines_read;
8458 }
8459 }
8460 else
8461 {
8462 --position.chars_read_current_line;
8463 }
8464
8466 {
8467 JSON_ASSERT(!token_string.empty());
8468 token_string.pop_back();
8469 }
8470 }
8471
8473 void add(char_int_type c)
8474 {
8475 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8476 }
8477
8478 public:
8480 // value getters
8482
8484 constexpr number_integer_t get_number_integer() const noexcept
8485 {
8486 return value_integer;
8487 }
8488
8490 constexpr number_unsigned_t get_number_unsigned() const noexcept
8491 {
8492 return value_unsigned;
8493 }
8494
8496 constexpr number_float_t get_number_float() const noexcept
8497 {
8498 return value_float;
8499 }
8500
8502 string_t& get_string()
8503 {
8504 // translate decimal points from locale back to '.' (#4084)
8505 if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
8506 {
8507 token_buffer[decimal_point_position] = '.';
8508 }
8509 return token_buffer;
8510 }
8511
8513 // diagnostics
8515
8517 constexpr position_t get_position() const noexcept
8518 {
8519 return position;
8520 }
8521
8525 std::string get_token_string() const
8526 {
8527 // escape control characters
8528 std::string result;
8529 for (const auto c : token_string)
8530 {
8531 if (static_cast<unsigned char>(c) <= '\x1F')
8532 {
8533 // escape control characters
8534 std::array<char, 9> cs{{}};
8535 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8536 result += cs.data();
8537 }
8538 else
8539 {
8540 // add character as is
8541 result.push_back(static_cast<std::string::value_type>(c));
8542 }
8543 }
8544
8545 return result;
8546 }
8547
8550 constexpr const char* get_error_message() const noexcept
8551 {
8552 return error_message;
8553 }
8554
8556 // actual scanner
8558
8564 {
8565 if (get() == 0xEF)
8566 {
8567 // check if we completely parse the BOM
8568 return get() == 0xBB && get() == 0xBF;
8569 }
8570
8571 // the first character is not the beginning of the BOM; unget it to
8572 // process is later
8573 unget();
8574 return true;
8575 }
8576
8578 {
8579 do
8580 {
8581 get();
8582 }
8583 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8584 }
8585
8587 {
8588 // initially, skip the BOM
8589 if (position.chars_read_total == 0 && !skip_bom())
8590 {
8591 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8592 return token_type::parse_error;
8593 }
8594
8595 // read the next character and ignore whitespace
8597
8598 // ignore comments
8599 while (ignore_comments && current == '/')
8600 {
8601 if (!scan_comment())
8602 {
8603 return token_type::parse_error;
8604 }
8605
8606 // skip following whitespace
8608 }
8609
8610 switch (current)
8611 {
8612 // structural characters
8613 case '[':
8614 return token_type::begin_array;
8615 case ']':
8616 return token_type::end_array;
8617 case '{':
8618 return token_type::begin_object;
8619 case '}':
8620 return token_type::end_object;
8621 case ':':
8622 return token_type::name_separator;
8623 case ',':
8624 return token_type::value_separator;
8625
8626 // literals
8627 case 't':
8628 {
8629 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
8630 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8631 }
8632 case 'f':
8633 {
8634 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
8635 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8636 }
8637 case 'n':
8638 {
8639 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
8640 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8641 }
8642
8643 // string
8644 case '\"':
8645 return scan_string();
8646
8647 // number
8648 case '-':
8649 case '0':
8650 case '1':
8651 case '2':
8652 case '3':
8653 case '4':
8654 case '5':
8655 case '6':
8656 case '7':
8657 case '8':
8658 case '9':
8659 return scan_number();
8660
8661 // end of input (the null byte is needed when parsing from
8662 // string literals)
8663 case '\0':
8665 return token_type::end_of_input;
8666
8667 // error
8668 default:
8669 error_message = "invalid literal";
8670 return token_type::parse_error;
8671 }
8672 }
8673
8674 private:
8676 InputAdapterType ia;
8677
8679 const bool ignore_comments = false;
8680
8682 char_int_type current = char_traits<char_type>::eof();
8683
8685 bool next_unget = false;
8686
8688 position_t position {};
8689
8691 std::vector<char_type> token_string {};
8692
8694 string_t token_buffer {};
8695
8697 const char* error_message = "";
8698
8699 // number values
8700 number_integer_t value_integer = 0;
8701 number_unsigned_t value_unsigned = 0;
8702 number_float_t value_float = 0;
8703
8705 const char_int_type decimal_point_char = '.';
8707 std::size_t decimal_point_position = std::string::npos;
8708};
8709
8710} // namespace detail
8712
8713// #include <nlohmann/detail/macro_scope.hpp>
8714
8715// #include <nlohmann/detail/string_concat.hpp>
8716
8718
8727template<typename BasicJsonType>
8729{
8730 using number_integer_t = typename BasicJsonType::number_integer_t;
8731 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8732 using number_float_t = typename BasicJsonType::number_float_t;
8733 using string_t = typename BasicJsonType::string_t;
8734 using binary_t = typename BasicJsonType::binary_t;
8735
8740 virtual bool null() = 0;
8741
8747 virtual bool boolean(bool val) = 0;
8748
8754 virtual bool number_integer(number_integer_t val) = 0;
8755
8761 virtual bool number_unsigned(number_unsigned_t val) = 0;
8762
8769 virtual bool number_float(number_float_t val, const string_t& s) = 0;
8770
8777 virtual bool string(string_t& val) = 0;
8778
8785 virtual bool binary(binary_t& val) = 0;
8786
8793 virtual bool start_object(std::size_t elements) = 0;
8794
8801 virtual bool key(string_t& val) = 0;
8802
8807 virtual bool end_object() = 0;
8808
8815 virtual bool start_array(std::size_t elements) = 0;
8816
8821 virtual bool end_array() = 0;
8822
8830 virtual bool parse_error(std::size_t position,
8831 const std::string& last_token,
8832 const detail::exception& ex) = 0;
8833
8834 json_sax() = default;
8835 json_sax(const json_sax&) = default;
8836 json_sax(json_sax&&) noexcept = default;
8837 json_sax& operator=(const json_sax&) = default;
8838 json_sax& operator=(json_sax&&) noexcept = default;
8839 virtual ~json_sax() = default;
8840};
8841
8842namespace detail
8843{
8844constexpr std::size_t unknown_size()
8845{
8846 return (std::numeric_limits<std::size_t>::max)();
8847}
8848
8862template<typename BasicJsonType, typename InputAdapterType>
8864{
8865 public:
8866 using number_integer_t = typename BasicJsonType::number_integer_t;
8867 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8868 using number_float_t = typename BasicJsonType::number_float_t;
8869 using string_t = typename BasicJsonType::string_t;
8870 using binary_t = typename BasicJsonType::binary_t;
8872
8878 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
8879 : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
8880 {}
8881
8882 // make class move-only
8884 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8886 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8888
8889 bool null()
8890 {
8891 handle_value(nullptr);
8892 return true;
8893 }
8894
8895 bool boolean(bool val)
8896 {
8897 handle_value(val);
8898 return true;
8899 }
8900
8902 {
8903 handle_value(val);
8904 return true;
8905 }
8906
8908 {
8909 handle_value(val);
8910 return true;
8911 }
8912
8913 bool number_float(number_float_t val, const string_t& /*unused*/)
8914 {
8915 handle_value(val);
8916 return true;
8917 }
8918
8919 bool string(string_t& val)
8920 {
8921 handle_value(val);
8922 return true;
8923 }
8924
8925 bool binary(binary_t& val)
8926 {
8927 handle_value(std::move(val));
8928 return true;
8929 }
8930
8931 bool start_object(std::size_t len)
8932 {
8933 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
8934
8935#if JSON_DIAGNOSTIC_POSITIONS
8936 // Manually set the start position of the object here.
8937 // Ensure this is after the call to handle_value to ensure correct start position.
8938 if (m_lexer_ref)
8939 {
8940 // Lexer has read the first character of the object, so
8941 // subtract 1 from the position to get the correct start position.
8942 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8943 }
8944#endif
8945
8946 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8947 {
8948 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
8949 }
8950
8951 return true;
8952 }
8953
8954 bool key(string_t& val)
8955 {
8956 JSON_ASSERT(!ref_stack.empty());
8957 JSON_ASSERT(ref_stack.back()->is_object());
8958
8959 // add null at the given key and store the reference for later
8960 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
8961 return true;
8962 }
8963
8965 {
8966 JSON_ASSERT(!ref_stack.empty());
8967 JSON_ASSERT(ref_stack.back()->is_object());
8968
8969#if JSON_DIAGNOSTIC_POSITIONS
8970 if (m_lexer_ref)
8971 {
8972 // Lexer's position is past the closing brace, so set that as the end position.
8973 ref_stack.back()->end_position = m_lexer_ref->get_position();
8974 }
8975#endif
8976
8977 ref_stack.back()->set_parents();
8978 ref_stack.pop_back();
8979 return true;
8980 }
8981
8982 bool start_array(std::size_t len)
8983 {
8984 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
8985
8986#if JSON_DIAGNOSTIC_POSITIONS
8987 // Manually set the start position of the array here.
8988 // Ensure this is after the call to handle_value to ensure correct start position.
8989 if (m_lexer_ref)
8990 {
8991 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8992 }
8993#endif
8994
8995 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8996 {
8997 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
8998 }
8999
9000 return true;
9001 }
9002
9004 {
9005 JSON_ASSERT(!ref_stack.empty());
9006 JSON_ASSERT(ref_stack.back()->is_array());
9007
9008#if JSON_DIAGNOSTIC_POSITIONS
9009 if (m_lexer_ref)
9010 {
9011 // Lexer's position is past the closing bracket, so set that as the end position.
9012 ref_stack.back()->end_position = m_lexer_ref->get_position();
9013 }
9014#endif
9015
9016 ref_stack.back()->set_parents();
9017 ref_stack.pop_back();
9018 return true;
9019 }
9020
9021 template<class Exception>
9022 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9023 const Exception& ex)
9024 {
9025 errored = true;
9026 static_cast<void>(ex);
9027 if (allow_exceptions)
9028 {
9029 JSON_THROW(ex);
9030 }
9031 return false;
9032 }
9033
9034 constexpr bool is_errored() const
9035 {
9036 return errored;
9037 }
9038
9039 private:
9040
9041#if JSON_DIAGNOSTIC_POSITIONS
9042 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9043 {
9044 if (m_lexer_ref)
9045 {
9046 // Lexer has read past the current field value, so set the end position to the current position.
9047 // The start position will be set below based on the length of the string representation
9048 // of the value.
9049 v.end_position = m_lexer_ref->get_position();
9050
9051 switch (v.type())
9052 {
9053 case value_t::boolean:
9054 {
9055 // 4 and 5 are the string length of "true" and "false"
9056 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9057 break;
9058 }
9059
9060 case value_t::null:
9061 {
9062 // 4 is the string length of "null"
9063 v.start_position = v.end_position - 4;
9064 break;
9065 }
9066
9067 case value_t::string:
9068 {
9069 // include the length of the quotes, which is 2
9070 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9071 break;
9072 }
9073
9074 // As we handle the start and end positions for values created during parsing,
9075 // we do not expect the following value type to be called. Regardless, set the positions
9076 // in case this is created manually or through a different constructor. Exclude from lcov
9077 // since the exact condition of this switch is esoteric.
9078 // LCOV_EXCL_START
9079 case value_t::discarded:
9080 {
9081 v.end_position = std::string::npos;
9082 v.start_position = v.end_position;
9083 break;
9084 }
9085 // LCOV_EXCL_STOP
9086 case value_t::binary:
9087 case value_t::number_integer:
9088 case value_t::number_unsigned:
9089 case value_t::number_float:
9090 {
9091 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9092 break;
9093 }
9094 case value_t::object:
9095 case value_t::array:
9096 {
9097 // object and array are handled in start_object() and start_array() handlers
9098 // skip setting the values here.
9099 break;
9100 }
9101 default: // LCOV_EXCL_LINE
9102 // Handle all possible types discretely, default handler should never be reached.
9103 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9104 }
9105 }
9106 }
9107#endif
9108
9115 template<typename Value>
9117 BasicJsonType* handle_value(Value&& v)
9118 {
9119 if (ref_stack.empty())
9120 {
9121 root = BasicJsonType(std::forward<Value>(v));
9122
9123#if JSON_DIAGNOSTIC_POSITIONS
9124 handle_diagnostic_positions_for_json_value(root);
9125#endif
9126
9127 return &root;
9128 }
9129
9130 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9131
9132 if (ref_stack.back()->is_array())
9133 {
9134 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
9135
9136#if JSON_DIAGNOSTIC_POSITIONS
9137 handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
9138#endif
9139
9140 return &(ref_stack.back()->m_data.m_value.array->back());
9141 }
9142
9143 JSON_ASSERT(ref_stack.back()->is_object());
9144 JSON_ASSERT(object_element);
9145 *object_element = BasicJsonType(std::forward<Value>(v));
9146
9147#if JSON_DIAGNOSTIC_POSITIONS
9148 handle_diagnostic_positions_for_json_value(*object_element);
9149#endif
9150
9151 return object_element;
9152 }
9153
9155 BasicJsonType& root;
9157 std::vector<BasicJsonType*> ref_stack {};
9159 BasicJsonType* object_element = nullptr;
9161 bool errored = false;
9163 const bool allow_exceptions = true;
9165 lexer_t* m_lexer_ref = nullptr;
9166};
9167
9168template<typename BasicJsonType, typename InputAdapterType>
9170{
9171 public:
9172 using number_integer_t = typename BasicJsonType::number_integer_t;
9173 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9174 using number_float_t = typename BasicJsonType::number_float_t;
9175 using string_t = typename BasicJsonType::string_t;
9176 using binary_t = typename BasicJsonType::binary_t;
9177 using parser_callback_t = typename BasicJsonType::parser_callback_t;
9178 using parse_event_t = typename BasicJsonType::parse_event_t;
9180
9183 const bool allow_exceptions_ = true,
9184 lexer_t* lexer_ = nullptr)
9185 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
9186 {
9187 keep_stack.push_back(true);
9188 }
9189
9190 // make class move-only
9192 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9194 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9196
9197 bool null()
9198 {
9199 handle_value(nullptr);
9200 return true;
9201 }
9202
9203 bool boolean(bool val)
9204 {
9205 handle_value(val);
9206 return true;
9207 }
9208
9210 {
9211 handle_value(val);
9212 return true;
9213 }
9214
9216 {
9217 handle_value(val);
9218 return true;
9219 }
9220
9221 bool number_float(number_float_t val, const string_t& /*unused*/)
9222 {
9223 handle_value(val);
9224 return true;
9225 }
9226
9227 bool string(string_t& val)
9228 {
9229 handle_value(val);
9230 return true;
9231 }
9232
9233 bool binary(binary_t& val)
9234 {
9235 handle_value(std::move(val));
9236 return true;
9237 }
9238
9239 bool start_object(std::size_t len)
9240 {
9241 // check callback for object start
9242 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
9243 keep_stack.push_back(keep);
9244
9245 auto val = handle_value(BasicJsonType::value_t::object, true);
9246 ref_stack.push_back(val.second);
9247
9248 if (ref_stack.back())
9249 {
9250
9251#if JSON_DIAGNOSTIC_POSITIONS
9252 // Manually set the start position of the object here.
9253 // Ensure this is after the call to handle_value to ensure correct start position.
9254 if (m_lexer_ref)
9255 {
9256 // Lexer has read the first character of the object, so
9257 // subtract 1 from the position to get the correct start position.
9258 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9259 }
9260#endif
9261
9262 // check object limit
9263 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9264 {
9265 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
9266 }
9267 }
9268 return true;
9269 }
9270
9271 bool key(string_t& val)
9272 {
9273 BasicJsonType k = BasicJsonType(val);
9274
9275 // check callback for the key
9276 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
9277 key_keep_stack.push_back(keep);
9278
9279 // add discarded value at the given key and store the reference for later
9280 if (keep && ref_stack.back())
9281 {
9282 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
9283 }
9284
9285 return true;
9286 }
9287
9289 {
9290 if (ref_stack.back())
9291 {
9292 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
9293 {
9294 // discard object
9295 *ref_stack.back() = discarded;
9296
9297#if JSON_DIAGNOSTIC_POSITIONS
9298 // Set start/end positions for discarded object.
9299 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9300#endif
9301 }
9302 else
9303 {
9304
9305#if JSON_DIAGNOSTIC_POSITIONS
9306 if (m_lexer_ref)
9307 {
9308 // Lexer's position is past the closing brace, so set that as the end position.
9309 ref_stack.back()->end_position = m_lexer_ref->get_position();
9310 }
9311#endif
9312
9313 ref_stack.back()->set_parents();
9314 }
9315 }
9316
9317 JSON_ASSERT(!ref_stack.empty());
9318 JSON_ASSERT(!keep_stack.empty());
9319 ref_stack.pop_back();
9320 keep_stack.pop_back();
9321
9322 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
9323 {
9324 // remove discarded value
9325 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
9326 {
9327 if (it->is_discarded())
9328 {
9329 ref_stack.back()->erase(it);
9330 break;
9331 }
9332 }
9333 }
9334
9335 return true;
9336 }
9337
9338 bool start_array(std::size_t len)
9339 {
9340 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
9341 keep_stack.push_back(keep);
9342
9343 auto val = handle_value(BasicJsonType::value_t::array, true);
9344 ref_stack.push_back(val.second);
9345
9346 if (ref_stack.back())
9347 {
9348
9349#if JSON_DIAGNOSTIC_POSITIONS
9350 // Manually set the start position of the array here.
9351 // Ensure this is after the call to handle_value to ensure correct start position.
9352 if (m_lexer_ref)
9353 {
9354 // Lexer has read the first character of the array, so
9355 // subtract 1 from the position to get the correct start position.
9356 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9357 }
9358#endif
9359
9360 // check array limit
9361 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9362 {
9363 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9364 }
9365 }
9366
9367 return true;
9368 }
9369
9371 {
9372 bool keep = true;
9373
9374 if (ref_stack.back())
9375 {
9376 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
9377 if (keep)
9378 {
9379
9380#if JSON_DIAGNOSTIC_POSITIONS
9381 if (m_lexer_ref)
9382 {
9383 // Lexer's position is past the closing bracket, so set that as the end position.
9384 ref_stack.back()->end_position = m_lexer_ref->get_position();
9385 }
9386#endif
9387
9388 ref_stack.back()->set_parents();
9389 }
9390 else
9391 {
9392 // discard array
9393 *ref_stack.back() = discarded;
9394
9395#if JSON_DIAGNOSTIC_POSITIONS
9396 // Set start/end positions for discarded array.
9397 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9398#endif
9399 }
9400 }
9401
9402 JSON_ASSERT(!ref_stack.empty());
9403 JSON_ASSERT(!keep_stack.empty());
9404 ref_stack.pop_back();
9405 keep_stack.pop_back();
9406
9407 // remove discarded value
9408 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
9409 {
9410 ref_stack.back()->m_data.m_value.array->pop_back();
9411 }
9412
9413 return true;
9414 }
9415
9416 template<class Exception>
9417 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9418 const Exception& ex)
9419 {
9420 errored = true;
9421 static_cast<void>(ex);
9422 if (allow_exceptions)
9423 {
9424 JSON_THROW(ex);
9425 }
9426 return false;
9427 }
9428
9429 constexpr bool is_errored() const
9430 {
9431 return errored;
9432 }
9433
9434 private:
9435
9436#if JSON_DIAGNOSTIC_POSITIONS
9437 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9438 {
9439 if (m_lexer_ref)
9440 {
9441 // Lexer has read past the current field value, so set the end position to the current position.
9442 // The start position will be set below based on the length of the string representation
9443 // of the value.
9444 v.end_position = m_lexer_ref->get_position();
9445
9446 switch (v.type())
9447 {
9448 case value_t::boolean:
9449 {
9450 // 4 and 5 are the string length of "true" and "false"
9451 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9452 break;
9453 }
9454
9455 case value_t::null:
9456 {
9457 // 4 is the string length of "null"
9458 v.start_position = v.end_position - 4;
9459 break;
9460 }
9461
9462 case value_t::string:
9463 {
9464 // include the length of the quotes, which is 2
9465 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9466 break;
9467 }
9468
9469 case value_t::discarded:
9470 {
9471 v.end_position = std::string::npos;
9472 v.start_position = v.end_position;
9473 break;
9474 }
9475
9476 case value_t::binary:
9477 case value_t::number_integer:
9478 case value_t::number_unsigned:
9479 case value_t::number_float:
9480 {
9481 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9482 break;
9483 }
9484
9485 case value_t::object:
9486 case value_t::array:
9487 {
9488 // object and array are handled in start_object() and start_array() handlers
9489 // skip setting the values here.
9490 break;
9491 }
9492 default: // LCOV_EXCL_LINE
9493 // Handle all possible types discretely, default handler should never be reached.
9494 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9495 }
9496 }
9497 }
9498#endif
9499
9515 template<typename Value>
9516 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
9517 {
9518 JSON_ASSERT(!keep_stack.empty());
9519
9520 // do not handle this value if we know it would be added to a discarded
9521 // container
9522 if (!keep_stack.back())
9523 {
9524 return {false, nullptr};
9525 }
9526
9527 // create value
9528 auto value = BasicJsonType(std::forward<Value>(v));
9529
9530#if JSON_DIAGNOSTIC_POSITIONS
9531 handle_diagnostic_positions_for_json_value(value);
9532#endif
9533
9534 // check callback
9535 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
9536
9537 // do not handle this value if we just learnt it shall be discarded
9538 if (!keep)
9539 {
9540 return {false, nullptr};
9541 }
9542
9543 if (ref_stack.empty())
9544 {
9545 root = std::move(value);
9546 return {true, & root};
9547 }
9548
9549 // skip this value if we already decided to skip the parent
9550 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
9551 if (!ref_stack.back())
9552 {
9553 return {false, nullptr};
9554 }
9555
9556 // we now only expect arrays and objects
9557 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9558
9559 // array
9560 if (ref_stack.back()->is_array())
9561 {
9562 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
9563 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
9564 }
9565
9566 // object
9567 JSON_ASSERT(ref_stack.back()->is_object());
9568 // check if we should store an element for the current key
9569 JSON_ASSERT(!key_keep_stack.empty());
9570 const bool store_element = key_keep_stack.back();
9571 key_keep_stack.pop_back();
9572
9573 if (!store_element)
9574 {
9575 return {false, nullptr};
9576 }
9577
9578 JSON_ASSERT(object_element);
9579 *object_element = std::move(value);
9580 return {true, object_element};
9581 }
9582
9584 BasicJsonType& root;
9586 std::vector<BasicJsonType*> ref_stack {};
9588 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
9590 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
9592 BasicJsonType* object_element = nullptr;
9594 bool errored = false;
9596 const parser_callback_t callback = nullptr;
9598 const bool allow_exceptions = true;
9600 BasicJsonType discarded = BasicJsonType::value_t::discarded;
9602 lexer_t* m_lexer_ref = nullptr;
9603};
9604
9605template<typename BasicJsonType>
9607{
9608 public:
9609 using number_integer_t = typename BasicJsonType::number_integer_t;
9610 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9611 using number_float_t = typename BasicJsonType::number_float_t;
9612 using string_t = typename BasicJsonType::string_t;
9613 using binary_t = typename BasicJsonType::binary_t;
9614
9615 bool null()
9616 {
9617 return true;
9618 }
9619
9620 bool boolean(bool /*unused*/)
9621 {
9622 return true;
9623 }
9624
9626 {
9627 return true;
9628 }
9629
9631 {
9632 return true;
9633 }
9634
9635 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
9636 {
9637 return true;
9638 }
9639
9640 bool string(string_t& /*unused*/)
9641 {
9642 return true;
9643 }
9644
9645 bool binary(binary_t& /*unused*/)
9646 {
9647 return true;
9648 }
9649
9650 bool start_object(std::size_t /*unused*/ = detail::unknown_size())
9651 {
9652 return true;
9653 }
9654
9655 bool key(string_t& /*unused*/)
9656 {
9657 return true;
9658 }
9659
9661 {
9662 return true;
9663 }
9664
9665 bool start_array(std::size_t /*unused*/ = detail::unknown_size())
9666 {
9667 return true;
9668 }
9669
9671 {
9672 return true;
9673 }
9674
9675 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
9676 {
9677 return false;
9678 }
9679};
9680
9681} // namespace detail
9683
9684// #include <nlohmann/detail/input/lexer.hpp>
9685
9686// #include <nlohmann/detail/macro_scope.hpp>
9687
9688// #include <nlohmann/detail/meta/is_sax.hpp>
9689// __ _____ _____ _____
9690// __| | __| | | | JSON for Modern C++
9691// | | |__ | | | | | | version 3.12.0
9692// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9693//
9694// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
9695// SPDX-License-Identifier: MIT
9696
9697
9698
9699#include <cstdint> // size_t
9700#include <utility> // declval
9701#include <string> // string
9702
9703// #include <nlohmann/detail/abi_macros.hpp>
9704
9705// #include <nlohmann/detail/meta/detected.hpp>
9706
9707// #include <nlohmann/detail/meta/type_traits.hpp>
9708
9709
9711namespace detail
9712{
9713
9714template<typename T>
9715using null_function_t = decltype(std::declval<T&>().null());
9716
9717template<typename T>
9719 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9720
9721template<typename T, typename Integer>
9723 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9724
9725template<typename T, typename Unsigned>
9727 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9728
9729template<typename T, typename Float, typename String>
9730using number_float_function_t = decltype(std::declval<T&>().number_float(
9731 std::declval<Float>(), std::declval<const String&>()));
9732
9733template<typename T, typename String>
9735 decltype(std::declval<T&>().string(std::declval<String&>()));
9736
9737template<typename T, typename Binary>
9739 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9740
9741template<typename T>
9743 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9744
9745template<typename T, typename String>
9747 decltype(std::declval<T&>().key(std::declval<String&>()));
9748
9749template<typename T>
9750using end_object_function_t = decltype(std::declval<T&>().end_object());
9751
9752template<typename T>
9754 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9755
9756template<typename T>
9757using end_array_function_t = decltype(std::declval<T&>().end_array());
9758
9759template<typename T, typename Exception>
9760using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9761 std::declval<std::size_t>(), std::declval<const std::string&>(),
9762 std::declval<const Exception&>()));
9763
9764template<typename SAX, typename BasicJsonType>
9766{
9767 private:
9769 "BasicJsonType must be of type basic_json<...>");
9770
9771 using number_integer_t = typename BasicJsonType::number_integer_t;
9772 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9773 using number_float_t = typename BasicJsonType::number_float_t;
9774 using string_t = typename BasicJsonType::string_t;
9775 using binary_t = typename BasicJsonType::binary_t;
9776 using exception_t = typename BasicJsonType::exception;
9777
9778 public:
9779 static constexpr bool value =
9793};
9794
9795template<typename SAX, typename BasicJsonType>
9797{
9798 private:
9800 "BasicJsonType must be of type basic_json<...>");
9801
9802 using number_integer_t = typename BasicJsonType::number_integer_t;
9803 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9804 using number_float_t = typename BasicJsonType::number_float_t;
9805 using string_t = typename BasicJsonType::string_t;
9806 using binary_t = typename BasicJsonType::binary_t;
9807 using exception_t = typename BasicJsonType::exception;
9808
9809 public:
9811 "Missing/invalid function: bool null()");
9813 "Missing/invalid function: bool boolean(bool)");
9815 "Missing/invalid function: bool boolean(bool)");
9816 static_assert(
9818 number_integer_t>::value,
9819 "Missing/invalid function: bool number_integer(number_integer_t)");
9820 static_assert(
9822 number_unsigned_t>::value,
9823 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9824 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9825 number_float_t, string_t>::value,
9826 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9827 static_assert(
9829 "Missing/invalid function: bool string(string_t&)");
9830 static_assert(
9832 "Missing/invalid function: bool binary(binary_t&)");
9834 "Missing/invalid function: bool start_object(std::size_t)");
9836 "Missing/invalid function: bool key(string_t&)");
9838 "Missing/invalid function: bool end_object()");
9840 "Missing/invalid function: bool start_array(std::size_t)");
9842 "Missing/invalid function: bool end_array()");
9843 static_assert(
9845 "Missing/invalid function: bool parse_error(std::size_t, const "
9846 "std::string&, const exception&)");
9847};
9848
9849} // namespace detail
9851
9852// #include <nlohmann/detail/meta/type_traits.hpp>
9853
9854// #include <nlohmann/detail/string_concat.hpp>
9855
9856// #include <nlohmann/detail/value_t.hpp>
9857
9858
9860namespace detail
9861{
9862
9870
9878inline bool little_endianness(int num = 1) noexcept
9879{
9880 return *reinterpret_cast<char*>(&num) == 1;
9881}
9882
9884// binary reader //
9886
9890template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
9892{
9893 using number_integer_t = typename BasicJsonType::number_integer_t;
9894 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9895 using number_float_t = typename BasicJsonType::number_float_t;
9896 using string_t = typename BasicJsonType::string_t;
9897 using binary_t = typename BasicJsonType::binary_t;
9898 using json_sax_t = SAX;
9899 using char_type = typename InputAdapterType::char_type;
9900 using char_int_type = typename char_traits<char_type>::int_type;
9901
9902 public:
9908 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9909 {
9911 }
9912
9913 // make class move-only
9915 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9917 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9918 ~binary_reader() = default;
9919
9929 bool sax_parse(const input_format_t format,
9930 json_sax_t* sax_,
9931 const bool strict = true,
9932 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9933 {
9934 sax = sax_;
9935 bool result = false;
9936
9937 switch (format)
9938 {
9940 result = parse_bson_internal();
9941 break;
9942
9944 result = parse_cbor_internal(true, tag_handler);
9945 break;
9946
9948 result = parse_msgpack_internal();
9949 break;
9950
9953 result = parse_ubjson_internal();
9954 break;
9955
9956 case input_format_t::json: // LCOV_EXCL_LINE
9957 default: // LCOV_EXCL_LINE
9958 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9959 }
9960
9961 // strict mode: next byte must be EOF
9962 if (result && strict)
9963 {
9964 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9965 {
9966 get_ignore_noop();
9967 }
9968 else
9969 {
9970 get();
9971 }
9972
9974 {
9975 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9976 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9977 }
9978 }
9979
9980 return result;
9981 }
9982
9983 private:
9985 // BSON //
9987
9992 bool parse_bson_internal()
9993 {
9994 std::int32_t document_size{};
9995 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9996
9997 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
9998 {
9999 return false;
10000 }
10001
10002 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
10003 {
10004 return false;
10005 }
10006
10007 return sax->end_object();
10008 }
10009
10017 bool get_bson_cstr(string_t& result)
10018 {
10019 auto out = std::back_inserter(result);
10020 while (true)
10021 {
10022 get();
10023 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
10024 {
10025 return false;
10026 }
10027 if (current == 0x00)
10028 {
10029 return true;
10030 }
10031 *out++ = static_cast<typename string_t::value_type>(current);
10032 }
10033 }
10034
10046 template<typename NumberType>
10047 bool get_bson_string(const NumberType len, string_t& result)
10048 {
10049 if (JSON_HEDLEY_UNLIKELY(len < 1))
10050 {
10051 auto last_token = get_token_string();
10052 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10053 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
10054 }
10055
10056 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
10057 }
10058
10068 template<typename NumberType>
10069 bool get_bson_binary(const NumberType len, binary_t& result)
10070 {
10071 if (JSON_HEDLEY_UNLIKELY(len < 0))
10072 {
10073 auto last_token = get_token_string();
10074 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10075 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
10076 }
10077
10078 // All BSON binary values have a subtype
10079 std::uint8_t subtype{};
10080 get_number<std::uint8_t>(input_format_t::bson, subtype);
10081 result.set_subtype(subtype);
10082
10083 return get_binary(input_format_t::bson, len, result);
10084 }
10085
10096 bool parse_bson_element_internal(const char_int_type element_type,
10097 const std::size_t element_type_parse_position)
10098 {
10099 switch (element_type)
10100 {
10101 case 0x01: // double
10102 {
10103 double number{};
10104 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10105 }
10106
10107 case 0x02: // string
10108 {
10109 std::int32_t len{};
10110 string_t value;
10111 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
10112 }
10113
10114 case 0x03: // object
10115 {
10116 return parse_bson_internal();
10117 }
10118
10119 case 0x04: // array
10120 {
10121 return parse_bson_array();
10122 }
10123
10124 case 0x05: // binary
10125 {
10126 std::int32_t len{};
10127 binary_t value;
10128 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
10129 }
10130
10131 case 0x08: // boolean
10132 {
10133 return sax->boolean(get() != 0);
10134 }
10135
10136 case 0x0A: // null
10137 {
10138 return sax->null();
10139 }
10140
10141 case 0x10: // int32
10142 {
10143 std::int32_t value{};
10144 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10145 }
10146
10147 case 0x12: // int64
10148 {
10149 std::int64_t value{};
10150 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10151 }
10152
10153 case 0x11: // uint64
10154 {
10155 std::uint64_t value{};
10156 return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
10157 }
10158
10159 default: // anything else is not supported (yet)
10160 {
10161 std::array<char, 3> cr{{}};
10162 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10163 const std::string cr_str{cr.data()};
10164 return sax->parse_error(element_type_parse_position, cr_str,
10165 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
10166 }
10167 }
10168 }
10169
10182 bool parse_bson_element_list(const bool is_array)
10183 {
10184 string_t key;
10185
10186 while (auto element_type = get())
10187 {
10188 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
10189 {
10190 return false;
10191 }
10192
10193 const std::size_t element_type_parse_position = chars_read;
10194 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
10195 {
10196 return false;
10197 }
10198
10199 if (!is_array && !sax->key(key))
10200 {
10201 return false;
10202 }
10203
10204 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
10205 {
10206 return false;
10207 }
10208
10209 // get_bson_cstr only appends
10210 key.clear();
10211 }
10212
10213 return true;
10214 }
10215
10220 bool parse_bson_array()
10221 {
10222 std::int32_t document_size{};
10223 get_number<std::int32_t, true>(input_format_t::bson, document_size);
10224
10225 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
10226 {
10227 return false;
10228 }
10229
10230 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
10231 {
10232 return false;
10233 }
10234
10235 return sax->end_array();
10236 }
10237
10239 // CBOR //
10241
10250 bool parse_cbor_internal(const bool get_char,
10251 const cbor_tag_handler_t tag_handler)
10252 {
10253 switch (get_char ? get() : current)
10254 {
10255 // EOF
10256 case char_traits<char_type>::eof():
10257 return unexpect_eof(input_format_t::cbor, "value");
10258
10259 // Integer 0x00..0x17 (0..23)
10260 case 0x00:
10261 case 0x01:
10262 case 0x02:
10263 case 0x03:
10264 case 0x04:
10265 case 0x05:
10266 case 0x06:
10267 case 0x07:
10268 case 0x08:
10269 case 0x09:
10270 case 0x0A:
10271 case 0x0B:
10272 case 0x0C:
10273 case 0x0D:
10274 case 0x0E:
10275 case 0x0F:
10276 case 0x10:
10277 case 0x11:
10278 case 0x12:
10279 case 0x13:
10280 case 0x14:
10281 case 0x15:
10282 case 0x16:
10283 case 0x17:
10284 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10285
10286 case 0x18: // Unsigned integer (one-byte uint8_t follows)
10287 {
10288 std::uint8_t number{};
10289 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10290 }
10291
10292 case 0x19: // Unsigned integer (two-byte uint16_t follows)
10293 {
10294 std::uint16_t number{};
10295 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10296 }
10297
10298 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
10299 {
10300 std::uint32_t number{};
10301 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10302 }
10303
10304 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
10305 {
10306 std::uint64_t number{};
10307 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10308 }
10309
10310 // Negative integer -1-0x00..-1-0x17 (-1..-24)
10311 case 0x20:
10312 case 0x21:
10313 case 0x22:
10314 case 0x23:
10315 case 0x24:
10316 case 0x25:
10317 case 0x26:
10318 case 0x27:
10319 case 0x28:
10320 case 0x29:
10321 case 0x2A:
10322 case 0x2B:
10323 case 0x2C:
10324 case 0x2D:
10325 case 0x2E:
10326 case 0x2F:
10327 case 0x30:
10328 case 0x31:
10329 case 0x32:
10330 case 0x33:
10331 case 0x34:
10332 case 0x35:
10333 case 0x36:
10334 case 0x37:
10335 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
10336
10337 case 0x38: // Negative integer (one-byte uint8_t follows)
10338 {
10339 std::uint8_t number{};
10340 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10341 }
10342
10343 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
10344 {
10345 std::uint16_t number{};
10346 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10347 }
10348
10349 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
10350 {
10351 std::uint32_t number{};
10352 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10353 }
10354
10355 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
10356 {
10357 std::uint64_t number{};
10358 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
10359 - static_cast<number_integer_t>(number));
10360 }
10361
10362 // Binary data (0x00..0x17 bytes follow)
10363 case 0x40:
10364 case 0x41:
10365 case 0x42:
10366 case 0x43:
10367 case 0x44:
10368 case 0x45:
10369 case 0x46:
10370 case 0x47:
10371 case 0x48:
10372 case 0x49:
10373 case 0x4A:
10374 case 0x4B:
10375 case 0x4C:
10376 case 0x4D:
10377 case 0x4E:
10378 case 0x4F:
10379 case 0x50:
10380 case 0x51:
10381 case 0x52:
10382 case 0x53:
10383 case 0x54:
10384 case 0x55:
10385 case 0x56:
10386 case 0x57:
10387 case 0x58: // Binary data (one-byte uint8_t for n follows)
10388 case 0x59: // Binary data (two-byte uint16_t for n follow)
10389 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10390 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10391 case 0x5F: // Binary data (indefinite length)
10392 {
10393 binary_t b;
10394 return get_cbor_binary(b) && sax->binary(b);
10395 }
10396
10397 // UTF-8 string (0x00..0x17 bytes follow)
10398 case 0x60:
10399 case 0x61:
10400 case 0x62:
10401 case 0x63:
10402 case 0x64:
10403 case 0x65:
10404 case 0x66:
10405 case 0x67:
10406 case 0x68:
10407 case 0x69:
10408 case 0x6A:
10409 case 0x6B:
10410 case 0x6C:
10411 case 0x6D:
10412 case 0x6E:
10413 case 0x6F:
10414 case 0x70:
10415 case 0x71:
10416 case 0x72:
10417 case 0x73:
10418 case 0x74:
10419 case 0x75:
10420 case 0x76:
10421 case 0x77:
10422 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10423 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10424 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10425 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10426 case 0x7F: // UTF-8 string (indefinite length)
10427 {
10428 string_t s;
10429 return get_cbor_string(s) && sax->string(s);
10430 }
10431
10432 // array (0x00..0x17 data items follow)
10433 case 0x80:
10434 case 0x81:
10435 case 0x82:
10436 case 0x83:
10437 case 0x84:
10438 case 0x85:
10439 case 0x86:
10440 case 0x87:
10441 case 0x88:
10442 case 0x89:
10443 case 0x8A:
10444 case 0x8B:
10445 case 0x8C:
10446 case 0x8D:
10447 case 0x8E:
10448 case 0x8F:
10449 case 0x90:
10450 case 0x91:
10451 case 0x92:
10452 case 0x93:
10453 case 0x94:
10454 case 0x95:
10455 case 0x96:
10456 case 0x97:
10457 return get_cbor_array(
10458 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10459
10460 case 0x98: // array (one-byte uint8_t for n follows)
10461 {
10462 std::uint8_t len{};
10463 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10464 }
10465
10466 case 0x99: // array (two-byte uint16_t for n follow)
10467 {
10468 std::uint16_t len{};
10469 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10470 }
10471
10472 case 0x9A: // array (four-byte uint32_t for n follow)
10473 {
10474 std::uint32_t len{};
10475 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10476 }
10477
10478 case 0x9B: // array (eight-byte uint64_t for n follow)
10479 {
10480 std::uint64_t len{};
10481 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10482 }
10483
10484 case 0x9F: // array (indefinite length)
10485 return get_cbor_array(detail::unknown_size(), tag_handler);
10486
10487 // map (0x00..0x17 pairs of data items follow)
10488 case 0xA0:
10489 case 0xA1:
10490 case 0xA2:
10491 case 0xA3:
10492 case 0xA4:
10493 case 0xA5:
10494 case 0xA6:
10495 case 0xA7:
10496 case 0xA8:
10497 case 0xA9:
10498 case 0xAA:
10499 case 0xAB:
10500 case 0xAC:
10501 case 0xAD:
10502 case 0xAE:
10503 case 0xAF:
10504 case 0xB0:
10505 case 0xB1:
10506 case 0xB2:
10507 case 0xB3:
10508 case 0xB4:
10509 case 0xB5:
10510 case 0xB6:
10511 case 0xB7:
10512 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10513
10514 case 0xB8: // map (one-byte uint8_t for n follows)
10515 {
10516 std::uint8_t len{};
10517 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10518 }
10519
10520 case 0xB9: // map (two-byte uint16_t for n follow)
10521 {
10522 std::uint16_t len{};
10523 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10524 }
10525
10526 case 0xBA: // map (four-byte uint32_t for n follow)
10527 {
10528 std::uint32_t len{};
10529 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10530 }
10531
10532 case 0xBB: // map (eight-byte uint64_t for n follow)
10533 {
10534 std::uint64_t len{};
10535 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10536 }
10537
10538 case 0xBF: // map (indefinite length)
10539 return get_cbor_object(detail::unknown_size(), tag_handler);
10540
10541 case 0xC6: // tagged item
10542 case 0xC7:
10543 case 0xC8:
10544 case 0xC9:
10545 case 0xCA:
10546 case 0xCB:
10547 case 0xCC:
10548 case 0xCD:
10549 case 0xCE:
10550 case 0xCF:
10551 case 0xD0:
10552 case 0xD1:
10553 case 0xD2:
10554 case 0xD3:
10555 case 0xD4:
10556 case 0xD8: // tagged item (1 byte follows)
10557 case 0xD9: // tagged item (2 bytes follow)
10558 case 0xDA: // tagged item (4 bytes follow)
10559 case 0xDB: // tagged item (8 bytes follow)
10560 {
10561 switch (tag_handler)
10562 {
10563 case cbor_tag_handler_t::error:
10564 {
10565 auto last_token = get_token_string();
10566 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10567 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10568 }
10569
10570 case cbor_tag_handler_t::ignore:
10571 {
10572 // ignore binary subtype
10573 switch (current)
10574 {
10575 case 0xD8:
10576 {
10577 std::uint8_t subtype_to_ignore{};
10578 get_number(input_format_t::cbor, subtype_to_ignore);
10579 break;
10580 }
10581 case 0xD9:
10582 {
10583 std::uint16_t subtype_to_ignore{};
10584 get_number(input_format_t::cbor, subtype_to_ignore);
10585 break;
10586 }
10587 case 0xDA:
10588 {
10589 std::uint32_t subtype_to_ignore{};
10590 get_number(input_format_t::cbor, subtype_to_ignore);
10591 break;
10592 }
10593 case 0xDB:
10594 {
10595 std::uint64_t subtype_to_ignore{};
10596 get_number(input_format_t::cbor, subtype_to_ignore);
10597 break;
10598 }
10599 default:
10600 break;
10601 }
10602 return parse_cbor_internal(true, tag_handler);
10603 }
10604
10605 case cbor_tag_handler_t::store:
10606 {
10607 binary_t b;
10608 // use binary subtype and store in a binary container
10609 switch (current)
10610 {
10611 case 0xD8:
10612 {
10613 std::uint8_t subtype{};
10614 get_number(input_format_t::cbor, subtype);
10616 break;
10617 }
10618 case 0xD9:
10619 {
10620 std::uint16_t subtype{};
10621 get_number(input_format_t::cbor, subtype);
10623 break;
10624 }
10625 case 0xDA:
10626 {
10627 std::uint32_t subtype{};
10628 get_number(input_format_t::cbor, subtype);
10630 break;
10631 }
10632 case 0xDB:
10633 {
10634 std::uint64_t subtype{};
10635 get_number(input_format_t::cbor, subtype);
10637 break;
10638 }
10639 default:
10640 return parse_cbor_internal(true, tag_handler);
10641 }
10642 get();
10643 return get_cbor_binary(b) && sax->binary(b);
10644 }
10645
10646 default: // LCOV_EXCL_LINE
10647 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10648 return false; // LCOV_EXCL_LINE
10649 }
10650 }
10651
10652 case 0xF4: // false
10653 return sax->boolean(false);
10654
10655 case 0xF5: // true
10656 return sax->boolean(true);
10657
10658 case 0xF6: // null
10659 return sax->null();
10660
10661 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10662 {
10663 const auto byte1_raw = get();
10664 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10665 {
10666 return false;
10667 }
10668 const auto byte2_raw = get();
10669 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10670 {
10671 return false;
10672 }
10673
10674 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10675 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10676
10677 // Code from RFC 7049, Appendix D, Figure 3:
10678 // As half-precision floating-point numbers were only added
10679 // to IEEE 754 in 2008, today's programming platforms often
10680 // still only have limited support for them. It is very
10681 // easy to include at least decoding support for them even
10682 // without such support. An example of a small decoder for
10683 // half-precision floating-point numbers in the C language
10684 // is shown in Fig. 3.
10685 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10686 const double val = [&half]
10687 {
10688 const int exp = (half >> 10u) & 0x1Fu;
10689 const unsigned int mant = half & 0x3FFu;
10690 JSON_ASSERT(0 <= exp&& exp <= 32);
10691 JSON_ASSERT(mant <= 1024);
10692 switch (exp)
10693 {
10694 case 0:
10695 return std::ldexp(mant, -24);
10696 case 31:
10697 return (mant == 0)
10698 ? std::numeric_limits<double>::infinity()
10699 : std::numeric_limits<double>::quiet_NaN();
10700 default:
10701 return std::ldexp(mant + 1024, exp - 25);
10702 }
10703 }();
10704 return sax->number_float((half & 0x8000u) != 0
10705 ? static_cast<number_float_t>(-val)
10706 : static_cast<number_float_t>(val), "");
10707 }
10708
10709 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10710 {
10711 float number{};
10712 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10713 }
10714
10715 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10716 {
10717 double number{};
10718 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10719 }
10720
10721 default: // anything else (0xFF is handled inside the other types)
10722 {
10723 auto last_token = get_token_string();
10724 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10725 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10726 }
10727 }
10728 }
10729
10741 bool get_cbor_string(string_t& result)
10742 {
10743 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10744 {
10745 return false;
10746 }
10747
10748 switch (current)
10749 {
10750 // UTF-8 string (0x00..0x17 bytes follow)
10751 case 0x60:
10752 case 0x61:
10753 case 0x62:
10754 case 0x63:
10755 case 0x64:
10756 case 0x65:
10757 case 0x66:
10758 case 0x67:
10759 case 0x68:
10760 case 0x69:
10761 case 0x6A:
10762 case 0x6B:
10763 case 0x6C:
10764 case 0x6D:
10765 case 0x6E:
10766 case 0x6F:
10767 case 0x70:
10768 case 0x71:
10769 case 0x72:
10770 case 0x73:
10771 case 0x74:
10772 case 0x75:
10773 case 0x76:
10774 case 0x77:
10775 {
10776 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10777 }
10778
10779 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10780 {
10781 std::uint8_t len{};
10782 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10783 }
10784
10785 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10786 {
10787 std::uint16_t len{};
10788 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10789 }
10790
10791 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10792 {
10793 std::uint32_t len{};
10794 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10795 }
10796
10797 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10798 {
10799 std::uint64_t len{};
10800 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10801 }
10802
10803 case 0x7F: // UTF-8 string (indefinite length)
10804 {
10805 while (get() != 0xFF)
10806 {
10807 string_t chunk;
10808 if (!get_cbor_string(chunk))
10809 {
10810 return false;
10811 }
10812 result.append(chunk);
10813 }
10814 return true;
10815 }
10816
10817 default:
10818 {
10819 auto last_token = get_token_string();
10820 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10821 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10822 }
10823 }
10824 }
10825
10837 bool get_cbor_binary(binary_t& result)
10838 {
10839 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10840 {
10841 return false;
10842 }
10843
10844 switch (current)
10845 {
10846 // Binary data (0x00..0x17 bytes follow)
10847 case 0x40:
10848 case 0x41:
10849 case 0x42:
10850 case 0x43:
10851 case 0x44:
10852 case 0x45:
10853 case 0x46:
10854 case 0x47:
10855 case 0x48:
10856 case 0x49:
10857 case 0x4A:
10858 case 0x4B:
10859 case 0x4C:
10860 case 0x4D:
10861 case 0x4E:
10862 case 0x4F:
10863 case 0x50:
10864 case 0x51:
10865 case 0x52:
10866 case 0x53:
10867 case 0x54:
10868 case 0x55:
10869 case 0x56:
10870 case 0x57:
10871 {
10872 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10873 }
10874
10875 case 0x58: // Binary data (one-byte uint8_t for n follows)
10876 {
10877 std::uint8_t len{};
10878 return get_number(input_format_t::cbor, len) &&
10879 get_binary(input_format_t::cbor, len, result);
10880 }
10881
10882 case 0x59: // Binary data (two-byte uint16_t for n follow)
10883 {
10884 std::uint16_t len{};
10885 return get_number(input_format_t::cbor, len) &&
10886 get_binary(input_format_t::cbor, len, result);
10887 }
10888
10889 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10890 {
10891 std::uint32_t len{};
10892 return get_number(input_format_t::cbor, len) &&
10893 get_binary(input_format_t::cbor, len, result);
10894 }
10895
10896 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10897 {
10898 std::uint64_t len{};
10899 return get_number(input_format_t::cbor, len) &&
10900 get_binary(input_format_t::cbor, len, result);
10901 }
10902
10903 case 0x5F: // Binary data (indefinite length)
10904 {
10905 while (get() != 0xFF)
10906 {
10907 binary_t chunk;
10908 if (!get_cbor_binary(chunk))
10909 {
10910 return false;
10911 }
10912 result.insert(result.end(), chunk.begin(), chunk.end());
10913 }
10914 return true;
10915 }
10916
10917 default:
10918 {
10919 auto last_token = get_token_string();
10920 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10921 exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
10922 }
10923 }
10924 }
10925
10932 bool get_cbor_array(const std::size_t len,
10933 const cbor_tag_handler_t tag_handler)
10934 {
10935 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10936 {
10937 return false;
10938 }
10939
10940 if (len != detail::unknown_size())
10941 {
10942 for (std::size_t i = 0; i < len; ++i)
10943 {
10944 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10945 {
10946 return false;
10947 }
10948 }
10949 }
10950 else
10951 {
10952 while (get() != 0xFF)
10953 {
10954 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10955 {
10956 return false;
10957 }
10958 }
10959 }
10960
10961 return sax->end_array();
10962 }
10963
10970 bool get_cbor_object(const std::size_t len,
10971 const cbor_tag_handler_t tag_handler)
10972 {
10973 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10974 {
10975 return false;
10976 }
10977
10978 if (len != 0)
10979 {
10980 string_t key;
10981 if (len != detail::unknown_size())
10982 {
10983 for (std::size_t i = 0; i < len; ++i)
10984 {
10985 get();
10986 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10987 {
10988 return false;
10989 }
10990
10991 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10992 {
10993 return false;
10994 }
10995 key.clear();
10996 }
10997 }
10998 else
10999 {
11000 while (get() != 0xFF)
11001 {
11002 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
11003 {
11004 return false;
11005 }
11006
11007 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
11008 {
11009 return false;
11010 }
11011 key.clear();
11012 }
11013 }
11014 }
11015
11016 return sax->end_object();
11017 }
11018
11020 // MsgPack //
11022
11026 bool parse_msgpack_internal()
11027 {
11028 switch (get())
11029 {
11030 // EOF
11031 case char_traits<char_type>::eof():
11032 return unexpect_eof(input_format_t::msgpack, "value");
11033
11034 // positive fixint
11035 case 0x00:
11036 case 0x01:
11037 case 0x02:
11038 case 0x03:
11039 case 0x04:
11040 case 0x05:
11041 case 0x06:
11042 case 0x07:
11043 case 0x08:
11044 case 0x09:
11045 case 0x0A:
11046 case 0x0B:
11047 case 0x0C:
11048 case 0x0D:
11049 case 0x0E:
11050 case 0x0F:
11051 case 0x10:
11052 case 0x11:
11053 case 0x12:
11054 case 0x13:
11055 case 0x14:
11056 case 0x15:
11057 case 0x16:
11058 case 0x17:
11059 case 0x18:
11060 case 0x19:
11061 case 0x1A:
11062 case 0x1B:
11063 case 0x1C:
11064 case 0x1D:
11065 case 0x1E:
11066 case 0x1F:
11067 case 0x20:
11068 case 0x21:
11069 case 0x22:
11070 case 0x23:
11071 case 0x24:
11072 case 0x25:
11073 case 0x26:
11074 case 0x27:
11075 case 0x28:
11076 case 0x29:
11077 case 0x2A:
11078 case 0x2B:
11079 case 0x2C:
11080 case 0x2D:
11081 case 0x2E:
11082 case 0x2F:
11083 case 0x30:
11084 case 0x31:
11085 case 0x32:
11086 case 0x33:
11087 case 0x34:
11088 case 0x35:
11089 case 0x36:
11090 case 0x37:
11091 case 0x38:
11092 case 0x39:
11093 case 0x3A:
11094 case 0x3B:
11095 case 0x3C:
11096 case 0x3D:
11097 case 0x3E:
11098 case 0x3F:
11099 case 0x40:
11100 case 0x41:
11101 case 0x42:
11102 case 0x43:
11103 case 0x44:
11104 case 0x45:
11105 case 0x46:
11106 case 0x47:
11107 case 0x48:
11108 case 0x49:
11109 case 0x4A:
11110 case 0x4B:
11111 case 0x4C:
11112 case 0x4D:
11113 case 0x4E:
11114 case 0x4F:
11115 case 0x50:
11116 case 0x51:
11117 case 0x52:
11118 case 0x53:
11119 case 0x54:
11120 case 0x55:
11121 case 0x56:
11122 case 0x57:
11123 case 0x58:
11124 case 0x59:
11125 case 0x5A:
11126 case 0x5B:
11127 case 0x5C:
11128 case 0x5D:
11129 case 0x5E:
11130 case 0x5F:
11131 case 0x60:
11132 case 0x61:
11133 case 0x62:
11134 case 0x63:
11135 case 0x64:
11136 case 0x65:
11137 case 0x66:
11138 case 0x67:
11139 case 0x68:
11140 case 0x69:
11141 case 0x6A:
11142 case 0x6B:
11143 case 0x6C:
11144 case 0x6D:
11145 case 0x6E:
11146 case 0x6F:
11147 case 0x70:
11148 case 0x71:
11149 case 0x72:
11150 case 0x73:
11151 case 0x74:
11152 case 0x75:
11153 case 0x76:
11154 case 0x77:
11155 case 0x78:
11156 case 0x79:
11157 case 0x7A:
11158 case 0x7B:
11159 case 0x7C:
11160 case 0x7D:
11161 case 0x7E:
11162 case 0x7F:
11163 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
11164
11165 // fixmap
11166 case 0x80:
11167 case 0x81:
11168 case 0x82:
11169 case 0x83:
11170 case 0x84:
11171 case 0x85:
11172 case 0x86:
11173 case 0x87:
11174 case 0x88:
11175 case 0x89:
11176 case 0x8A:
11177 case 0x8B:
11178 case 0x8C:
11179 case 0x8D:
11180 case 0x8E:
11181 case 0x8F:
11182 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11183
11184 // fixarray
11185 case 0x90:
11186 case 0x91:
11187 case 0x92:
11188 case 0x93:
11189 case 0x94:
11190 case 0x95:
11191 case 0x96:
11192 case 0x97:
11193 case 0x98:
11194 case 0x99:
11195 case 0x9A:
11196 case 0x9B:
11197 case 0x9C:
11198 case 0x9D:
11199 case 0x9E:
11200 case 0x9F:
11201 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11202
11203 // fixstr
11204 case 0xA0:
11205 case 0xA1:
11206 case 0xA2:
11207 case 0xA3:
11208 case 0xA4:
11209 case 0xA5:
11210 case 0xA6:
11211 case 0xA7:
11212 case 0xA8:
11213 case 0xA9:
11214 case 0xAA:
11215 case 0xAB:
11216 case 0xAC:
11217 case 0xAD:
11218 case 0xAE:
11219 case 0xAF:
11220 case 0xB0:
11221 case 0xB1:
11222 case 0xB2:
11223 case 0xB3:
11224 case 0xB4:
11225 case 0xB5:
11226 case 0xB6:
11227 case 0xB7:
11228 case 0xB8:
11229 case 0xB9:
11230 case 0xBA:
11231 case 0xBB:
11232 case 0xBC:
11233 case 0xBD:
11234 case 0xBE:
11235 case 0xBF:
11236 case 0xD9: // str 8
11237 case 0xDA: // str 16
11238 case 0xDB: // str 32
11239 {
11240 string_t s;
11241 return get_msgpack_string(s) && sax->string(s);
11242 }
11243
11244 case 0xC0: // nil
11245 return sax->null();
11246
11247 case 0xC2: // false
11248 return sax->boolean(false);
11249
11250 case 0xC3: // true
11251 return sax->boolean(true);
11252
11253 case 0xC4: // bin 8
11254 case 0xC5: // bin 16
11255 case 0xC6: // bin 32
11256 case 0xC7: // ext 8
11257 case 0xC8: // ext 16
11258 case 0xC9: // ext 32
11259 case 0xD4: // fixext 1
11260 case 0xD5: // fixext 2
11261 case 0xD6: // fixext 4
11262 case 0xD7: // fixext 8
11263 case 0xD8: // fixext 16
11264 {
11265 binary_t b;
11266 return get_msgpack_binary(b) && sax->binary(b);
11267 }
11268
11269 case 0xCA: // float 32
11270 {
11271 float number{};
11272 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11273 }
11274
11275 case 0xCB: // float 64
11276 {
11277 double number{};
11278 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11279 }
11280
11281 case 0xCC: // uint 8
11282 {
11283 std::uint8_t number{};
11284 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11285 }
11286
11287 case 0xCD: // uint 16
11288 {
11289 std::uint16_t number{};
11290 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11291 }
11292
11293 case 0xCE: // uint 32
11294 {
11295 std::uint32_t number{};
11296 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11297 }
11298
11299 case 0xCF: // uint 64
11300 {
11301 std::uint64_t number{};
11302 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11303 }
11304
11305 case 0xD0: // int 8
11306 {
11307 std::int8_t number{};
11308 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11309 }
11310
11311 case 0xD1: // int 16
11312 {
11313 std::int16_t number{};
11314 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11315 }
11316
11317 case 0xD2: // int 32
11318 {
11319 std::int32_t number{};
11320 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11321 }
11322
11323 case 0xD3: // int 64
11324 {
11325 std::int64_t number{};
11326 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11327 }
11328
11329 case 0xDC: // array 16
11330 {
11331 std::uint16_t len{};
11332 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
11333 }
11334
11335 case 0xDD: // array 32
11336 {
11337 std::uint32_t len{};
11338 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
11339 }
11340
11341 case 0xDE: // map 16
11342 {
11343 std::uint16_t len{};
11344 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
11345 }
11346
11347 case 0xDF: // map 32
11348 {
11349 std::uint32_t len{};
11350 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
11351 }
11352
11353 // negative fixint
11354 case 0xE0:
11355 case 0xE1:
11356 case 0xE2:
11357 case 0xE3:
11358 case 0xE4:
11359 case 0xE5:
11360 case 0xE6:
11361 case 0xE7:
11362 case 0xE8:
11363 case 0xE9:
11364 case 0xEA:
11365 case 0xEB:
11366 case 0xEC:
11367 case 0xED:
11368 case 0xEE:
11369 case 0xEF:
11370 case 0xF0:
11371 case 0xF1:
11372 case 0xF2:
11373 case 0xF3:
11374 case 0xF4:
11375 case 0xF5:
11376 case 0xF6:
11377 case 0xF7:
11378 case 0xF8:
11379 case 0xF9:
11380 case 0xFA:
11381 case 0xFB:
11382 case 0xFC:
11383 case 0xFD:
11384 case 0xFE:
11385 case 0xFF:
11386 return sax->number_integer(static_cast<std::int8_t>(current));
11387
11388 default: // anything else
11389 {
11390 auto last_token = get_token_string();
11391 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11392 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
11393 }
11394 }
11395 }
11396
11407 bool get_msgpack_string(string_t& result)
11408 {
11409 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
11410 {
11411 return false;
11412 }
11413
11414 switch (current)
11415 {
11416 // fixstr
11417 case 0xA0:
11418 case 0xA1:
11419 case 0xA2:
11420 case 0xA3:
11421 case 0xA4:
11422 case 0xA5:
11423 case 0xA6:
11424 case 0xA7:
11425 case 0xA8:
11426 case 0xA9:
11427 case 0xAA:
11428 case 0xAB:
11429 case 0xAC:
11430 case 0xAD:
11431 case 0xAE:
11432 case 0xAF:
11433 case 0xB0:
11434 case 0xB1:
11435 case 0xB2:
11436 case 0xB3:
11437 case 0xB4:
11438 case 0xB5:
11439 case 0xB6:
11440 case 0xB7:
11441 case 0xB8:
11442 case 0xB9:
11443 case 0xBA:
11444 case 0xBB:
11445 case 0xBC:
11446 case 0xBD:
11447 case 0xBE:
11448 case 0xBF:
11449 {
11450 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
11451 }
11452
11453 case 0xD9: // str 8
11454 {
11455 std::uint8_t len{};
11456 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11457 }
11458
11459 case 0xDA: // str 16
11460 {
11461 std::uint16_t len{};
11462 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11463 }
11464
11465 case 0xDB: // str 32
11466 {
11467 std::uint32_t len{};
11468 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11469 }
11470
11471 default:
11472 {
11473 auto last_token = get_token_string();
11474 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11475 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
11476 }
11477 }
11478 }
11479
11490 bool get_msgpack_binary(binary_t& result)
11491 {
11492 // helper function to set the subtype
11493 auto assign_and_return_true = [&result](std::int8_t subtype)
11494 {
11495 result.set_subtype(static_cast<std::uint8_t>(subtype));
11496 return true;
11497 };
11498
11499 switch (current)
11500 {
11501 case 0xC4: // bin 8
11502 {
11503 std::uint8_t len{};
11504 return get_number(input_format_t::msgpack, len) &&
11505 get_binary(input_format_t::msgpack, len, result);
11506 }
11507
11508 case 0xC5: // bin 16
11509 {
11510 std::uint16_t len{};
11511 return get_number(input_format_t::msgpack, len) &&
11512 get_binary(input_format_t::msgpack, len, result);
11513 }
11514
11515 case 0xC6: // bin 32
11516 {
11517 std::uint32_t len{};
11518 return get_number(input_format_t::msgpack, len) &&
11519 get_binary(input_format_t::msgpack, len, result);
11520 }
11521
11522 case 0xC7: // ext 8
11523 {
11524 std::uint8_t len{};
11525 std::int8_t subtype{};
11526 return get_number(input_format_t::msgpack, len) &&
11527 get_number(input_format_t::msgpack, subtype) &&
11528 get_binary(input_format_t::msgpack, len, result) &&
11529 assign_and_return_true(subtype);
11530 }
11531
11532 case 0xC8: // ext 16
11533 {
11534 std::uint16_t len{};
11535 std::int8_t subtype{};
11536 return get_number(input_format_t::msgpack, len) &&
11537 get_number(input_format_t::msgpack, subtype) &&
11538 get_binary(input_format_t::msgpack, len, result) &&
11539 assign_and_return_true(subtype);
11540 }
11541
11542 case 0xC9: // ext 32
11543 {
11544 std::uint32_t len{};
11545 std::int8_t subtype{};
11546 return get_number(input_format_t::msgpack, len) &&
11547 get_number(input_format_t::msgpack, subtype) &&
11548 get_binary(input_format_t::msgpack, len, result) &&
11549 assign_and_return_true(subtype);
11550 }
11551
11552 case 0xD4: // fixext 1
11553 {
11554 std::int8_t subtype{};
11555 return get_number(input_format_t::msgpack, subtype) &&
11556 get_binary(input_format_t::msgpack, 1, result) &&
11557 assign_and_return_true(subtype);
11558 }
11559
11560 case 0xD5: // fixext 2
11561 {
11562 std::int8_t subtype{};
11563 return get_number(input_format_t::msgpack, subtype) &&
11564 get_binary(input_format_t::msgpack, 2, result) &&
11565 assign_and_return_true(subtype);
11566 }
11567
11568 case 0xD6: // fixext 4
11569 {
11570 std::int8_t subtype{};
11571 return get_number(input_format_t::msgpack, subtype) &&
11572 get_binary(input_format_t::msgpack, 4, result) &&
11573 assign_and_return_true(subtype);
11574 }
11575
11576 case 0xD7: // fixext 8
11577 {
11578 std::int8_t subtype{};
11579 return get_number(input_format_t::msgpack, subtype) &&
11580 get_binary(input_format_t::msgpack, 8, result) &&
11581 assign_and_return_true(subtype);
11582 }
11583
11584 case 0xD8: // fixext 16
11585 {
11586 std::int8_t subtype{};
11587 return get_number(input_format_t::msgpack, subtype) &&
11588 get_binary(input_format_t::msgpack, 16, result) &&
11589 assign_and_return_true(subtype);
11590 }
11591
11592 default: // LCOV_EXCL_LINE
11593 return false; // LCOV_EXCL_LINE
11594 }
11595 }
11596
11601 bool get_msgpack_array(const std::size_t len)
11602 {
11603 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11604 {
11605 return false;
11606 }
11607
11608 for (std::size_t i = 0; i < len; ++i)
11609 {
11610 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11611 {
11612 return false;
11613 }
11614 }
11615
11616 return sax->end_array();
11617 }
11618
11623 bool get_msgpack_object(const std::size_t len)
11624 {
11625 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11626 {
11627 return false;
11628 }
11629
11630 string_t key;
11631 for (std::size_t i = 0; i < len; ++i)
11632 {
11633 get();
11634 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11635 {
11636 return false;
11637 }
11638
11639 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11640 {
11641 return false;
11642 }
11643 key.clear();
11644 }
11645
11646 return sax->end_object();
11647 }
11648
11650 // UBJSON //
11652
11660 bool parse_ubjson_internal(const bool get_char = true)
11661 {
11662 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11663 }
11664
11679 bool get_ubjson_string(string_t& result, const bool get_char = true)
11680 {
11681 if (get_char)
11682 {
11683 get(); // TODO(niels): may we ignore N here?
11684 }
11685
11686 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11687 {
11688 return false;
11689 }
11690
11691 switch (current)
11692 {
11693 case 'U':
11694 {
11695 std::uint8_t len{};
11696 return get_number(input_format, len) && get_string(input_format, len, result);
11697 }
11698
11699 case 'i':
11700 {
11701 std::int8_t len{};
11702 return get_number(input_format, len) && get_string(input_format, len, result);
11703 }
11704
11705 case 'I':
11706 {
11707 std::int16_t len{};
11708 return get_number(input_format, len) && get_string(input_format, len, result);
11709 }
11710
11711 case 'l':
11712 {
11713 std::int32_t len{};
11714 return get_number(input_format, len) && get_string(input_format, len, result);
11715 }
11716
11717 case 'L':
11718 {
11719 std::int64_t len{};
11720 return get_number(input_format, len) && get_string(input_format, len, result);
11721 }
11722
11723 case 'u':
11724 {
11725 if (input_format != input_format_t::bjdata)
11726 {
11727 break;
11728 }
11729 std::uint16_t len{};
11730 return get_number(input_format, len) && get_string(input_format, len, result);
11731 }
11732
11733 case 'm':
11734 {
11735 if (input_format != input_format_t::bjdata)
11736 {
11737 break;
11738 }
11739 std::uint32_t len{};
11740 return get_number(input_format, len) && get_string(input_format, len, result);
11741 }
11742
11743 case 'M':
11744 {
11745 if (input_format != input_format_t::bjdata)
11746 {
11747 break;
11748 }
11749 std::uint64_t len{};
11750 return get_number(input_format, len) && get_string(input_format, len, result);
11751 }
11752
11753 default:
11754 break;
11755 }
11756 auto last_token = get_token_string();
11757 std::string message;
11758
11759 if (input_format != input_format_t::bjdata)
11760 {
11761 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11762 }
11763 else
11764 {
11765 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11766 }
11767 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11768 }
11769
11774 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11775 {
11776 std::pair<std::size_t, char_int_type> size_and_type;
11777 size_t dimlen = 0;
11778 bool no_ndarray = true;
11779
11780 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11781 {
11782 return false;
11783 }
11784
11785 if (size_and_type.first != npos)
11786 {
11787 if (size_and_type.second != 0)
11788 {
11789 if (size_and_type.second != 'N')
11790 {
11791 for (std::size_t i = 0; i < size_and_type.first; ++i)
11792 {
11793 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11794 {
11795 return false;
11796 }
11797 dim.push_back(dimlen);
11798 }
11799 }
11800 }
11801 else
11802 {
11803 for (std::size_t i = 0; i < size_and_type.first; ++i)
11804 {
11805 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11806 {
11807 return false;
11808 }
11809 dim.push_back(dimlen);
11810 }
11811 }
11812 }
11813 else
11814 {
11815 while (current != ']')
11816 {
11817 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11818 {
11819 return false;
11820 }
11821 dim.push_back(dimlen);
11822 get_ignore_noop();
11823 }
11824 }
11825 return true;
11826 }
11827
11839 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11840 {
11841 if (prefix == 0)
11842 {
11843 prefix = get_ignore_noop();
11844 }
11845
11846 switch (prefix)
11847 {
11848 case 'U':
11849 {
11850 std::uint8_t number{};
11851 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11852 {
11853 return false;
11854 }
11855 result = static_cast<std::size_t>(number);
11856 return true;
11857 }
11858
11859 case 'i':
11860 {
11861 std::int8_t number{};
11862 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11863 {
11864 return false;
11865 }
11866 if (number < 0)
11867 {
11868 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11869 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11870 }
11871 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11872 return true;
11873 }
11874
11875 case 'I':
11876 {
11877 std::int16_t number{};
11878 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11879 {
11880 return false;
11881 }
11882 if (number < 0)
11883 {
11884 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11885 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11886 }
11887 result = static_cast<std::size_t>(number);
11888 return true;
11889 }
11890
11891 case 'l':
11892 {
11893 std::int32_t number{};
11894 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11895 {
11896 return false;
11897 }
11898 if (number < 0)
11899 {
11900 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11901 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11902 }
11903 result = static_cast<std::size_t>(number);
11904 return true;
11905 }
11906
11907 case 'L':
11908 {
11909 std::int64_t number{};
11910 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11911 {
11912 return false;
11913 }
11914 if (number < 0)
11915 {
11916 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11917 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11918 }
11919 if (!value_in_range_of<std::size_t>(number))
11920 {
11921 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11922 exception_message(input_format, "integer value overflow", "size"), nullptr));
11923 }
11924 result = static_cast<std::size_t>(number);
11925 return true;
11926 }
11927
11928 case 'u':
11929 {
11930 if (input_format != input_format_t::bjdata)
11931 {
11932 break;
11933 }
11934 std::uint16_t number{};
11935 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11936 {
11937 return false;
11938 }
11939 result = static_cast<std::size_t>(number);
11940 return true;
11941 }
11942
11943 case 'm':
11944 {
11945 if (input_format != input_format_t::bjdata)
11946 {
11947 break;
11948 }
11949 std::uint32_t number{};
11950 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11951 {
11952 return false;
11953 }
11954 result = conditional_static_cast<std::size_t>(number);
11955 return true;
11956 }
11957
11958 case 'M':
11959 {
11960 if (input_format != input_format_t::bjdata)
11961 {
11962 break;
11963 }
11964 std::uint64_t number{};
11965 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11966 {
11967 return false;
11968 }
11969 if (!value_in_range_of<std::size_t>(number))
11970 {
11971 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11972 exception_message(input_format, "integer value overflow", "size"), nullptr));
11973 }
11975 return true;
11976 }
11977
11978 case '[':
11979 {
11980 if (input_format != input_format_t::bjdata)
11981 {
11982 break;
11983 }
11984 if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
11985 {
11986 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr));
11987 }
11988 std::vector<size_t> dim;
11989 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11990 {
11991 return false;
11992 }
11993 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11994 {
11995 result = dim.at(dim.size() - 1);
11996 return true;
11997 }
11998 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11999 {
12000 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
12001 {
12002 if ( i == 0 )
12003 {
12004 result = 0;
12005 return true;
12006 }
12007 }
12008
12009 string_t key = "_ArraySize_";
12010 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
12011 {
12012 return false;
12013 }
12014 result = 1;
12015 for (auto i : dim)
12016 {
12017 // Pre-multiplication overflow check: if i > 0 and result > SIZE_MAX/i, then result*i would overflow.
12018 // This check must happen before multiplication since overflow detection after the fact is unreliable
12019 // as modular arithmetic can produce any value, not just 0 or SIZE_MAX.
12020 if (JSON_HEDLEY_UNLIKELY(i > 0 && result > (std::numeric_limits<std::size_t>::max)() / i))
12021 {
12022 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
12023 }
12024 result *= i;
12025 // Additional post-multiplication check to catch any edge cases the pre-check might miss
12026 if (result == 0 || result == npos)
12027 {
12028 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
12029 }
12030 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
12031 {
12032 return false;
12033 }
12034 }
12035 is_ndarray = true;
12036 return sax->end_array();
12037 }
12038 result = 0;
12039 return true;
12040 }
12041
12042 default:
12043 break;
12044 }
12045 auto last_token = get_token_string();
12046 std::string message;
12047
12048 if (input_format != input_format_t::bjdata)
12049 {
12050 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
12051 }
12052 else
12053 {
12054 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
12055 }
12056 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
12057 }
12058
12070 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
12071 {
12072 result.first = npos; // size
12073 result.second = 0; // type
12074 bool is_ndarray = false;
12075
12076 get_ignore_noop();
12077
12078 if (current == '$')
12079 {
12080 result.second = get(); // must not ignore 'N', because 'N' maybe the type
12081 if (input_format == input_format_t::bjdata
12082 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
12083 {
12084 auto last_token = get_token_string();
12085 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12086 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
12087 }
12088
12089 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
12090 {
12091 return false;
12092 }
12093
12094 get_ignore_noop();
12095 if (JSON_HEDLEY_UNLIKELY(current != '#'))
12096 {
12097 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
12098 {
12099 return false;
12100 }
12101 auto last_token = get_token_string();
12102 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12103 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
12104 }
12105
12106 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12107 if (input_format == input_format_t::bjdata && is_ndarray)
12108 {
12109 if (inside_ndarray)
12110 {
12111 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12112 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
12113 }
12114 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
12115 }
12116 return is_error;
12117 }
12118
12119 if (current == '#')
12120 {
12121 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12122 if (input_format == input_format_t::bjdata && is_ndarray)
12123 {
12124 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12125 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
12126 }
12127 return is_error;
12128 }
12129
12130 return true;
12131 }
12132
12137 bool get_ubjson_value(const char_int_type prefix)
12138 {
12139 switch (prefix)
12140 {
12141 case char_traits<char_type>::eof(): // EOF
12142 return unexpect_eof(input_format, "value");
12143
12144 case 'T': // true
12145 return sax->boolean(true);
12146 case 'F': // false
12147 return sax->boolean(false);
12148
12149 case 'Z': // null
12150 return sax->null();
12151
12152 case 'B': // byte
12153 {
12154 if (input_format != input_format_t::bjdata)
12155 {
12156 break;
12157 }
12158 std::uint8_t number{};
12159 return get_number(input_format, number) && sax->number_unsigned(number);
12160 }
12161
12162 case 'U':
12163 {
12164 std::uint8_t number{};
12165 return get_number(input_format, number) && sax->number_unsigned(number);
12166 }
12167
12168 case 'i':
12169 {
12170 std::int8_t number{};
12171 return get_number(input_format, number) && sax->number_integer(number);
12172 }
12173
12174 case 'I':
12175 {
12176 std::int16_t number{};
12177 return get_number(input_format, number) && sax->number_integer(number);
12178 }
12179
12180 case 'l':
12181 {
12182 std::int32_t number{};
12183 return get_number(input_format, number) && sax->number_integer(number);
12184 }
12185
12186 case 'L':
12187 {
12188 std::int64_t number{};
12189 return get_number(input_format, number) && sax->number_integer(number);
12190 }
12191
12192 case 'u':
12193 {
12194 if (input_format != input_format_t::bjdata)
12195 {
12196 break;
12197 }
12198 std::uint16_t number{};
12199 return get_number(input_format, number) && sax->number_unsigned(number);
12200 }
12201
12202 case 'm':
12203 {
12204 if (input_format != input_format_t::bjdata)
12205 {
12206 break;
12207 }
12208 std::uint32_t number{};
12209 return get_number(input_format, number) && sax->number_unsigned(number);
12210 }
12211
12212 case 'M':
12213 {
12214 if (input_format != input_format_t::bjdata)
12215 {
12216 break;
12217 }
12218 std::uint64_t number{};
12219 return get_number(input_format, number) && sax->number_unsigned(number);
12220 }
12221
12222 case 'h':
12223 {
12224 if (input_format != input_format_t::bjdata)
12225 {
12226 break;
12227 }
12228 const auto byte1_raw = get();
12229 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12230 {
12231 return false;
12232 }
12233 const auto byte2_raw = get();
12234 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12235 {
12236 return false;
12237 }
12238
12239 const auto byte1 = static_cast<unsigned char>(byte1_raw);
12240 const auto byte2 = static_cast<unsigned char>(byte2_raw);
12241
12242 // Code from RFC 7049, Appendix D, Figure 3:
12243 // As half-precision floating-point numbers were only added
12244 // to IEEE 754 in 2008, today's programming platforms often
12245 // still only have limited support for them. It is very
12246 // easy to include at least decoding support for them even
12247 // without such support. An example of a small decoder for
12248 // half-precision floating-point numbers in the C language
12249 // is shown in Fig. 3.
12250 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
12251 const double val = [&half]
12252 {
12253 const int exp = (half >> 10u) & 0x1Fu;
12254 const unsigned int mant = half & 0x3FFu;
12255 JSON_ASSERT(0 <= exp&& exp <= 32);
12256 JSON_ASSERT(mant <= 1024);
12257 switch (exp)
12258 {
12259 case 0:
12260 return std::ldexp(mant, -24);
12261 case 31:
12262 return (mant == 0)
12263 ? std::numeric_limits<double>::infinity()
12264 : std::numeric_limits<double>::quiet_NaN();
12265 default:
12266 return std::ldexp(mant + 1024, exp - 25);
12267 }
12268 }();
12269 return sax->number_float((half & 0x8000u) != 0
12270 ? static_cast<number_float_t>(-val)
12271 : static_cast<number_float_t>(val), "");
12272 }
12273
12274 case 'd':
12275 {
12276 float number{};
12277 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12278 }
12279
12280 case 'D':
12281 {
12282 double number{};
12283 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12284 }
12285
12286 case 'H':
12287 {
12288 return get_ubjson_high_precision_number();
12289 }
12290
12291 case 'C': // char
12292 {
12293 get();
12294 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
12295 {
12296 return false;
12297 }
12298 if (JSON_HEDLEY_UNLIKELY(current > 127))
12299 {
12300 auto last_token = get_token_string();
12301 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
12302 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
12303 }
12304 string_t s(1, static_cast<typename string_t::value_type>(current));
12305 return sax->string(s);
12306 }
12307
12308 case 'S': // string
12309 {
12310 string_t s;
12311 return get_ubjson_string(s) && sax->string(s);
12312 }
12313
12314 case '[': // array
12315 return get_ubjson_array();
12316
12317 case '{': // object
12318 return get_ubjson_object();
12319
12320 default: // anything else
12321 break;
12322 }
12323 auto last_token = get_token_string();
12324 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
12325 }
12326
12330 bool get_ubjson_array()
12331 {
12332 std::pair<std::size_t, char_int_type> size_and_type;
12333 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12334 {
12335 return false;
12336 }
12337
12338 // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
12339 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
12340
12341 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12342 {
12343 size_and_type.second &= ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
12344 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t)
12345 {
12346 return p.first < t;
12347 });
12348 string_t key = "_ArrayType_";
12349 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
12350 {
12351 auto last_token = get_token_string();
12352 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12353 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
12354 }
12355
12356 string_t type = it->second; // sax->string() takes a reference
12357 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
12358 {
12359 return false;
12360 }
12361
12362 if (size_and_type.second == 'C' || size_and_type.second == 'B')
12363 {
12364 size_and_type.second = 'U';
12365 }
12366
12367 key = "_ArrayData_";
12368 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
12369 {
12370 return false;
12371 }
12372
12373 for (std::size_t i = 0; i < size_and_type.first; ++i)
12374 {
12375 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12376 {
12377 return false;
12378 }
12379 }
12380
12381 return (sax->end_array() && sax->end_object());
12382 }
12383
12384 // If BJData type marker is 'B' decode as binary
12385 if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B')
12386 {
12387 binary_t result;
12388 return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
12389 }
12390
12391 if (size_and_type.first != npos)
12392 {
12393 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
12394 {
12395 return false;
12396 }
12397
12398 if (size_and_type.second != 0)
12399 {
12400 if (size_and_type.second != 'N')
12401 {
12402 for (std::size_t i = 0; i < size_and_type.first; ++i)
12403 {
12404 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12405 {
12406 return false;
12407 }
12408 }
12409 }
12410 }
12411 else
12412 {
12413 for (std::size_t i = 0; i < size_and_type.first; ++i)
12414 {
12415 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12416 {
12417 return false;
12418 }
12419 }
12420 }
12421 }
12422 else
12423 {
12424 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
12425 {
12426 return false;
12427 }
12428
12429 while (current != ']')
12430 {
12431 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
12432 {
12433 return false;
12434 }
12435 get_ignore_noop();
12436 }
12437 }
12438
12439 return sax->end_array();
12440 }
12441
12445 bool get_ubjson_object()
12446 {
12447 std::pair<std::size_t, char_int_type> size_and_type;
12448 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12449 {
12450 return false;
12451 }
12452
12453 // do not accept ND-array size in objects in BJData
12454 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12455 {
12456 auto last_token = get_token_string();
12457 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12458 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
12459 }
12460
12461 string_t key;
12462 if (size_and_type.first != npos)
12463 {
12464 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
12465 {
12466 return false;
12467 }
12468
12469 if (size_and_type.second != 0)
12470 {
12471 for (std::size_t i = 0; i < size_and_type.first; ++i)
12472 {
12473 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12474 {
12475 return false;
12476 }
12477 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12478 {
12479 return false;
12480 }
12481 key.clear();
12482 }
12483 }
12484 else
12485 {
12486 for (std::size_t i = 0; i < size_and_type.first; ++i)
12487 {
12488 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12489 {
12490 return false;
12491 }
12492 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12493 {
12494 return false;
12495 }
12496 key.clear();
12497 }
12498 }
12499 }
12500 else
12501 {
12502 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
12503 {
12504 return false;
12505 }
12506
12507 while (current != '}')
12508 {
12509 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
12510 {
12511 return false;
12512 }
12513 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12514 {
12515 return false;
12516 }
12517 get_ignore_noop();
12518 key.clear();
12519 }
12520 }
12521
12522 return sax->end_object();
12523 }
12524
12525 // Note, no reader for UBJSON binary types is implemented because they do
12526 // not exist
12527
12528 bool get_ubjson_high_precision_number()
12529 {
12530 // get the size of the following number string
12531 std::size_t size{};
12532 bool no_ndarray = true;
12533 auto res = get_ubjson_size_value(size, no_ndarray);
12534 if (JSON_HEDLEY_UNLIKELY(!res))
12535 {
12536 return res;
12537 }
12538
12539 // get number string
12540 std::vector<char> number_vector;
12541 for (std::size_t i = 0; i < size; ++i)
12542 {
12543 get();
12544 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12545 {
12546 return false;
12547 }
12548 number_vector.push_back(static_cast<char>(current));
12549 }
12550
12551 // parse number string
12552 using ia_type = decltype(detail::input_adapter(number_vector));
12553 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
12554 const auto result_number = number_lexer.scan();
12555 const auto number_string = number_lexer.get_token_string();
12556 const auto result_remainder = number_lexer.scan();
12557
12558 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12559
12560 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12561 {
12562 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12563 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12564 }
12565
12566 switch (result_number)
12567 {
12568 case token_type::value_integer:
12569 return sax->number_integer(number_lexer.get_number_integer());
12570 case token_type::value_unsigned:
12571 return sax->number_unsigned(number_lexer.get_number_unsigned());
12572 case token_type::value_float:
12573 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12574 case token_type::uninitialized:
12575 case token_type::literal_true:
12576 case token_type::literal_false:
12577 case token_type::literal_null:
12578 case token_type::value_string:
12579 case token_type::begin_array:
12580 case token_type::begin_object:
12581 case token_type::end_array:
12582 case token_type::end_object:
12583 case token_type::name_separator:
12584 case token_type::value_separator:
12585 case token_type::parse_error:
12586 case token_type::end_of_input:
12587 case token_type::literal_or_value:
12588 default:
12589 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12590 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12591 }
12592 }
12593
12595 // Utility functions //
12597
12607 char_int_type get()
12608 {
12609 ++chars_read;
12610 return current = ia.get_character();
12611 }
12612
12621 template<class T>
12622 bool get_to(T& dest, const input_format_t format, const char* context)
12623 {
12624 auto new_chars_read = ia.get_elements(&dest);
12625 chars_read += new_chars_read;
12626 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12627 {
12628 // in case of failure, advance position by 1 to report the failing location
12629 ++chars_read;
12630 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12631 return false;
12632 }
12633 return true;
12634 }
12635
12639 char_int_type get_ignore_noop()
12640 {
12641 do
12642 {
12643 get();
12644 }
12645 while (current == 'N');
12646
12647 return current;
12648 }
12649
12650 template<class NumberType>
12651 static void byte_swap(NumberType& number)
12652 {
12653 constexpr std::size_t sz = sizeof(number);
12654#ifdef __cpp_lib_byteswap
12655 if constexpr (sz == 1)
12656 {
12657 return;
12658 }
12659 else if constexpr(std::is_integral_v<NumberType>)
12660 {
12661 number = std::byteswap(number);
12662 return;
12663 }
12664 else
12665 {
12666#endif
12667 auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12668 for (std::size_t i = 0; i < sz / 2; ++i)
12669 {
12670 std::swap(ptr[i], ptr[sz - i - 1]);
12671 }
12672#ifdef __cpp_lib_byteswap
12673 }
12674#endif
12675 }
12676
12677 /*
12678 @brief read a number from the input
12679
12680 @tparam NumberType the type of the number
12681 @param[in] format the current format (for diagnostics)
12682 @param[out] result number of type @a NumberType
12683
12684 @return whether conversion completed
12685
12686 @note This function needs to respect the system's endianness, because
12687 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12688 (big endian) and therefore need reordering on little endian systems.
12689 On the other hand, BSON and BJData use little endian and should reorder
12690 on big endian systems.
12691 */
12692 template<typename NumberType, bool InputIsLittleEndian = false>
12693 bool get_number(const input_format_t format, NumberType& result)
12694 {
12695 // read in the original format
12696
12697 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12698 {
12699 return false;
12700 }
12701 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12702 {
12703 byte_swap(result);
12704 }
12705 return true;
12706 }
12707
12722 template<typename NumberType>
12723 bool get_string(const input_format_t format,
12724 const NumberType len,
12725 string_t& result)
12726 {
12727 bool success = true;
12728 for (NumberType i = 0; i < len; i++)
12729 {
12730 get();
12731 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12732 {
12733 success = false;
12734 break;
12735 }
12736 result.push_back(static_cast<typename string_t::value_type>(current));
12737 }
12738 return success;
12739 }
12740
12755 template<typename NumberType>
12756 bool get_binary(const input_format_t format,
12757 const NumberType len,
12758 binary_t& result)
12759 {
12760 bool success = true;
12761 for (NumberType i = 0; i < len; i++)
12762 {
12763 get();
12764 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12765 {
12766 success = false;
12767 break;
12768 }
12769 result.push_back(static_cast<typename binary_t::value_type>(current));
12770 }
12771 return success;
12772 }
12773
12780 bool unexpect_eof(const input_format_t format, const char* context) const
12781 {
12782 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12783 {
12784 return sax->parse_error(chars_read, "<end of file>",
12785 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12786 }
12787 return true;
12788 }
12789
12793 std::string get_token_string() const
12794 {
12795 std::array<char, 3> cr{{}};
12796 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12797 return std::string{cr.data()};
12798 }
12799
12806 std::string exception_message(const input_format_t format,
12807 const std::string& detail,
12808 const std::string& context) const
12809 {
12810 std::string error_msg = "syntax error while parsing ";
12811
12812 switch (format)
12813 {
12814 case input_format_t::cbor:
12815 error_msg += "CBOR";
12816 break;
12817
12818 case input_format_t::msgpack:
12819 error_msg += "MessagePack";
12820 break;
12821
12822 case input_format_t::ubjson:
12823 error_msg += "UBJSON";
12824 break;
12825
12826 case input_format_t::bson:
12827 error_msg += "BSON";
12828 break;
12829
12830 case input_format_t::bjdata:
12831 error_msg += "BJData";
12832 break;
12833
12834 case input_format_t::json: // LCOV_EXCL_LINE
12835 default: // LCOV_EXCL_LINE
12836 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12837 }
12838
12839 return concat(error_msg, ' ', context, ": ", detail);
12840 }
12841
12842 private:
12843 static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
12844
12846 InputAdapterType ia;
12847
12849 char_int_type current = char_traits<char_type>::eof();
12850
12852 std::size_t chars_read = 0;
12853
12855 const bool is_little_endian = little_endianness();
12856
12858 const input_format_t input_format = input_format_t::json;
12859
12861 json_sax_t* sax = nullptr;
12862
12863 // excluded markers in bjdata optimized type
12864#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12865 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12866
12867#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12868 make_array<bjd_type>( \
12869 bjd_type{'B', "byte"}, \
12870 bjd_type{'C', "char"}, \
12871 bjd_type{'D', "double"}, \
12872 bjd_type{'I', "int16"}, \
12873 bjd_type{'L', "int64"}, \
12874 bjd_type{'M', "uint64"}, \
12875 bjd_type{'U', "uint8"}, \
12876 bjd_type{'d', "single"}, \
12877 bjd_type{'i', "int8"}, \
12878 bjd_type{'l', "int32"}, \
12879 bjd_type{'m', "uint32"}, \
12880 bjd_type{'u', "uint16"})
12881
12883 // lookup tables
12884 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12885 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12887
12888 using bjd_type = std::pair<char_int_type, string_t>;
12889 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12890 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12892
12893#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12894#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12895};
12896
12897#ifndef JSON_HAS_CPP_17
12898 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12899 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12900#endif
12901
12902} // namespace detail
12904
12905// #include <nlohmann/detail/input/input_adapters.hpp>
12906
12907// #include <nlohmann/detail/input/lexer.hpp>
12908
12909// #include <nlohmann/detail/input/parser.hpp>
12910// __ _____ _____ _____
12911// __| | __| | | | JSON for Modern C++
12912// | | |__ | | | | | | version 3.12.0
12913// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12914//
12915// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
12916// SPDX-License-Identifier: MIT
12917
12918
12919
12920#include <cmath> // isfinite
12921#include <cstdint> // uint8_t
12922#include <functional> // function
12923#include <string> // string
12924#include <utility> // move
12925#include <vector> // vector
12926
12927// #include <nlohmann/detail/exceptions.hpp>
12928
12929// #include <nlohmann/detail/input/input_adapters.hpp>
12930
12931// #include <nlohmann/detail/input/json_sax.hpp>
12932
12933// #include <nlohmann/detail/input/lexer.hpp>
12934
12935// #include <nlohmann/detail/macro_scope.hpp>
12936
12937// #include <nlohmann/detail/meta/is_sax.hpp>
12938
12939// #include <nlohmann/detail/string_concat.hpp>
12940
12941// #include <nlohmann/detail/value_t.hpp>
12942
12943
12945namespace detail
12946{
12948// parser //
12950
12966
12967template<typename BasicJsonType>
12969 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12970
12976template<typename BasicJsonType, typename InputAdapterType>
12978{
12979 using number_integer_t = typename BasicJsonType::number_integer_t;
12980 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12981 using number_float_t = typename BasicJsonType::number_float_t;
12982 using string_t = typename BasicJsonType::string_t;
12984 using token_type = typename lexer_t::token_type;
12985
12986 public:
12988 explicit parser(InputAdapterType&& adapter,
12990 const bool allow_exceptions_ = true,
12991 const bool ignore_comments = false,
12992 const bool ignore_trailing_commas_ = false)
12993 : callback(std::move(cb))
12994 , m_lexer(std::move(adapter), ignore_comments)
12995 , allow_exceptions(allow_exceptions_)
12996 , ignore_trailing_commas(ignore_trailing_commas_)
12997 {
12998 // read first token
12999 get_token();
13000 }
13001
13012 void parse(const bool strict, BasicJsonType& result)
13013 {
13014 if (callback)
13015 {
13016 json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
13017 sax_parse_internal(&sdp);
13018
13019 // in strict mode, input must be completely read
13020 if (strict && (get_token() != token_type::end_of_input))
13021 {
13022 sdp.parse_error(m_lexer.get_position(),
13023 m_lexer.get_token_string(),
13024 parse_error::create(101, m_lexer.get_position(),
13025 exception_message(token_type::end_of_input, "value"), nullptr));
13026 }
13027
13028 // in case of an error, return a discarded value
13029 if (sdp.is_errored())
13030 {
13031 result = value_t::discarded;
13032 return;
13033 }
13034
13035 // set top-level value to null if it was discarded by the callback
13036 // function
13037 if (result.is_discarded())
13038 {
13039 result = nullptr;
13040 }
13041 }
13042 else
13043 {
13044 json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
13045 sax_parse_internal(&sdp);
13046
13047 // in strict mode, input must be completely read
13048 if (strict && (get_token() != token_type::end_of_input))
13049 {
13050 sdp.parse_error(m_lexer.get_position(),
13051 m_lexer.get_token_string(),
13052 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13053 }
13054
13055 // in case of an error, return a discarded value
13056 if (sdp.is_errored())
13057 {
13058 result = value_t::discarded;
13059 return;
13060 }
13061 }
13062
13063 result.assert_invariant();
13064 }
13065
13072 bool accept(const bool strict = true)
13073 {
13075 return sax_parse(&sax_acceptor, strict);
13076 }
13077
13078 template<typename SAX>
13080 bool sax_parse(SAX* sax, const bool strict = true)
13081 {
13083 const bool result = sax_parse_internal(sax);
13084
13085 // strict mode: next byte must be EOF
13086 if (result && strict && (get_token() != token_type::end_of_input))
13087 {
13088 return sax->parse_error(m_lexer.get_position(),
13089 m_lexer.get_token_string(),
13090 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13091 }
13092
13093 return result;
13094 }
13095
13096 private:
13097 template<typename SAX>
13099 bool sax_parse_internal(SAX* sax)
13100 {
13101 // stack to remember the hierarchy of structured values we are parsing
13102 // true = array; false = object
13103 std::vector<bool> states;
13104 // value to avoid a goto (see comment where set to true)
13105 bool skip_to_state_evaluation = false;
13106
13107 while (true)
13108 {
13109 if (!skip_to_state_evaluation)
13110 {
13111 // invariant: get_token() was called before each iteration
13112 switch (last_token)
13113 {
13114 case token_type::begin_object:
13115 {
13116 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
13117 {
13118 return false;
13119 }
13120
13121 // closing } -> we are done
13122 if (get_token() == token_type::end_object)
13123 {
13124 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13125 {
13126 return false;
13127 }
13128 break;
13129 }
13130
13131 // parse key
13132 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13133 {
13134 return sax->parse_error(m_lexer.get_position(),
13135 m_lexer.get_token_string(),
13136 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13137 }
13138 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13139 {
13140 return false;
13141 }
13142
13143 // parse separator (:)
13144 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13145 {
13146 return sax->parse_error(m_lexer.get_position(),
13147 m_lexer.get_token_string(),
13148 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13149 }
13150
13151 // remember we are now inside an object
13152 states.push_back(false);
13153
13154 // parse values
13155 get_token();
13156 continue;
13157 }
13158
13159 case token_type::begin_array:
13160 {
13161 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
13162 {
13163 return false;
13164 }
13165
13166 // closing ] -> we are done
13167 if (get_token() == token_type::end_array)
13168 {
13169 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13170 {
13171 return false;
13172 }
13173 break;
13174 }
13175
13176 // remember we are now inside an array
13177 states.push_back(true);
13178
13179 // parse values (no need to call get_token)
13180 continue;
13181 }
13182
13183 case token_type::value_float:
13184 {
13185 const auto res = m_lexer.get_number_float();
13186
13187 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
13188 {
13189 return sax->parse_error(m_lexer.get_position(),
13190 m_lexer.get_token_string(),
13191 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
13192 }
13193
13194 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
13195 {
13196 return false;
13197 }
13198
13199 break;
13200 }
13201
13202 case token_type::literal_false:
13203 {
13204 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
13205 {
13206 return false;
13207 }
13208 break;
13209 }
13210
13211 case token_type::literal_null:
13212 {
13213 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
13214 {
13215 return false;
13216 }
13217 break;
13218 }
13219
13220 case token_type::literal_true:
13221 {
13222 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
13223 {
13224 return false;
13225 }
13226 break;
13227 }
13228
13229 case token_type::value_integer:
13230 {
13231 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
13232 {
13233 return false;
13234 }
13235 break;
13236 }
13237
13238 case token_type::value_string:
13239 {
13240 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
13241 {
13242 return false;
13243 }
13244 break;
13245 }
13246
13247 case token_type::value_unsigned:
13248 {
13249 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
13250 {
13251 return false;
13252 }
13253 break;
13254 }
13255
13256 case token_type::parse_error:
13257 {
13258 // using "uninitialized" to avoid an "expected" message
13259 return sax->parse_error(m_lexer.get_position(),
13260 m_lexer.get_token_string(),
13261 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
13262 }
13263 case token_type::end_of_input:
13264 {
13265 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
13266 {
13267 return sax->parse_error(m_lexer.get_position(),
13268 m_lexer.get_token_string(),
13269 parse_error::create(101, m_lexer.get_position(),
13270 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
13271 }
13272
13273 return sax->parse_error(m_lexer.get_position(),
13274 m_lexer.get_token_string(),
13275 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13276 }
13277 case token_type::uninitialized:
13278 case token_type::end_array:
13279 case token_type::end_object:
13280 case token_type::name_separator:
13281 case token_type::value_separator:
13282 case token_type::literal_or_value:
13283 default: // the last token was unexpected
13284 {
13285 return sax->parse_error(m_lexer.get_position(),
13286 m_lexer.get_token_string(),
13287 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13288 }
13289 }
13290 }
13291 else
13292 {
13293 skip_to_state_evaluation = false;
13294 }
13295
13296 // we reached this line after we successfully parsed a value
13297 if (states.empty())
13298 {
13299 // empty stack: we reached the end of the hierarchy: done
13300 return true;
13301 }
13302
13303 if (states.back()) // array
13304 {
13305 // comma -> next value
13306 // or end of array (ignore_trailing_commas = true)
13307 if (get_token() == token_type::value_separator)
13308 {
13309 // parse a new value
13310 get_token();
13311
13312 // if ignore_trailing_commas and last_token is ], we can continue to "closing ]"
13313 if (!(ignore_trailing_commas && last_token == token_type::end_array))
13314 {
13315 continue;
13316 }
13317 }
13318
13319 // closing ]
13320 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
13321 {
13322 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13323 {
13324 return false;
13325 }
13326
13327 // We are done with this array. Before we can parse a
13328 // new value, we need to evaluate the new state first.
13329 // By setting skip_to_state_evaluation to false, we
13330 // are effectively jumping to the beginning of this if.
13331 JSON_ASSERT(!states.empty());
13332 states.pop_back();
13333 skip_to_state_evaluation = true;
13334 continue;
13335 }
13336
13337 return sax->parse_error(m_lexer.get_position(),
13338 m_lexer.get_token_string(),
13339 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
13340 }
13341
13342 // states.back() is false -> object
13343
13344 // comma -> next value
13345 // or end of object (ignore_trailing_commas = true)
13346 if (get_token() == token_type::value_separator)
13347 {
13348 get_token();
13349
13350 // if ignore_trailing_commas and last_token is }, we can continue to "closing }"
13351 if (!(ignore_trailing_commas && last_token == token_type::end_object))
13352 {
13353 // parse key
13354 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13355 {
13356 return sax->parse_error(m_lexer.get_position(),
13357 m_lexer.get_token_string(),
13358 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13359 }
13360
13361 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13362 {
13363 return false;
13364 }
13365
13366 // parse separator (:)
13367 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13368 {
13369 return sax->parse_error(m_lexer.get_position(),
13370 m_lexer.get_token_string(),
13371 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13372 }
13373
13374 // parse values
13375 get_token();
13376 continue;
13377 }
13378 }
13379
13380 // closing }
13381 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
13382 {
13383 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13384 {
13385 return false;
13386 }
13387
13388 // We are done with this object. Before we can parse a
13389 // new value, we need to evaluate the new state first.
13390 // By setting skip_to_state_evaluation to false, we
13391 // are effectively jumping to the beginning of this if.
13392 JSON_ASSERT(!states.empty());
13393 states.pop_back();
13394 skip_to_state_evaluation = true;
13395 continue;
13396 }
13397
13398 return sax->parse_error(m_lexer.get_position(),
13399 m_lexer.get_token_string(),
13400 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
13401 }
13402 }
13403
13405 token_type get_token()
13406 {
13407 return last_token = m_lexer.scan();
13408 }
13409
13410 std::string exception_message(const token_type expected, const std::string& context)
13411 {
13412 std::string error_msg = "syntax error ";
13413
13414 if (!context.empty())
13415 {
13416 error_msg += concat("while parsing ", context, ' ');
13417 }
13418
13419 error_msg += "- ";
13420
13421 if (last_token == token_type::parse_error)
13422 {
13423 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
13424 m_lexer.get_token_string(), '\'');
13425 }
13426 else
13427 {
13428 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
13429 }
13430
13431 if (expected != token_type::uninitialized)
13432 {
13433 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
13434 }
13435
13436 return error_msg;
13437 }
13438
13439 private:
13441 const parser_callback_t<BasicJsonType> callback = nullptr;
13443 token_type last_token = token_type::uninitialized;
13445 lexer_t m_lexer;
13447 const bool allow_exceptions = true;
13449 const bool ignore_trailing_commas = false;
13450};
13451
13452} // namespace detail
13454
13455// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13456// __ _____ _____ _____
13457// __| | __| | | | JSON for Modern C++
13458// | | |__ | | | | | | version 3.12.0
13459// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13460//
13461// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13462// SPDX-License-Identifier: MIT
13463
13464
13465
13466// #include <nlohmann/detail/abi_macros.hpp>
13467
13468// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13469// __ _____ _____ _____
13470// __| | __| | | | JSON for Modern C++
13471// | | |__ | | | | | | version 3.12.0
13472// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13473//
13474// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13475// SPDX-License-Identifier: MIT
13476
13477
13478
13479#include <cstddef> // ptrdiff_t
13480#include <limits> // numeric_limits
13481
13482// #include <nlohmann/detail/macro_scope.hpp>
13483
13484
13486namespace detail
13487{
13488
13489/*
13490@brief an iterator for primitive JSON types
13491
13492This class models an iterator for primitive JSON types (boolean, number,
13493string). Its only purpose is to allow the iterator/const_iterator classes
13494to "iterate" over primitive values. Internally, the iterator is modeled by
13495a `difference_type` variable. Value begin_value (`0`) models the begin and
13496end_value (`1`) models past the end.
13497*/
13499{
13500 private:
13501 using difference_type = std::ptrdiff_t;
13502 static constexpr difference_type begin_value = 0;
13503 static constexpr difference_type end_value = begin_value + 1;
13504
13507 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
13508
13509 public:
13510 constexpr difference_type get_value() const noexcept
13511 {
13512 return m_it;
13513 }
13514
13516 void set_begin() noexcept
13517 {
13518 m_it = begin_value;
13519 }
13520
13522 void set_end() noexcept
13523 {
13524 m_it = end_value;
13525 }
13526
13528 constexpr bool is_begin() const noexcept
13529 {
13530 return m_it == begin_value;
13531 }
13532
13534 constexpr bool is_end() const noexcept
13535 {
13536 return m_it == end_value;
13537 }
13538
13539 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13540 {
13541 return lhs.m_it == rhs.m_it;
13542 }
13543
13544 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13545 {
13546 return lhs.m_it < rhs.m_it;
13547 }
13548
13549 primitive_iterator_t operator+(difference_type n) noexcept
13550 {
13551 auto result = *this;
13552 result += n;
13553 return result;
13554 }
13555
13556 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13557 {
13558 return lhs.m_it - rhs.m_it;
13559 }
13560
13562 {
13563 ++m_it;
13564 return *this;
13565 }
13566
13567 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
13568 {
13569 auto result = *this;
13570 ++m_it;
13571 return result;
13572 }
13573
13575 {
13576 --m_it;
13577 return *this;
13578 }
13579
13580 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13581 {
13582 auto result = *this;
13583 --m_it;
13584 return result;
13585 }
13586
13587 primitive_iterator_t& operator+=(difference_type n) noexcept
13588 {
13589 m_it += n;
13590 return *this;
13591 }
13592
13593 primitive_iterator_t& operator-=(difference_type n) noexcept
13594 {
13595 m_it -= n;
13596 return *this;
13597 }
13598};
13599
13600} // namespace detail
13602
13603
13605namespace detail
13606{
13607
13614template<typename BasicJsonType> struct internal_iterator
13615{
13617 typename BasicJsonType::object_t::iterator object_iterator {};
13619 typename BasicJsonType::array_t::iterator array_iterator {};
13622};
13623
13624} // namespace detail
13626
13627// #include <nlohmann/detail/iterators/iter_impl.hpp>
13628// __ _____ _____ _____
13629// __| | __| | | | JSON for Modern C++
13630// | | |__ | | | | | | version 3.12.0
13631// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13632//
13633// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13634// SPDX-License-Identifier: MIT
13635
13636
13637
13638#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13639#include <type_traits> // conditional, is_const, remove_const
13640
13641// #include <nlohmann/detail/exceptions.hpp>
13642
13643// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13644
13645// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13646
13647// #include <nlohmann/detail/macro_scope.hpp>
13648
13649// #include <nlohmann/detail/meta/cpp_future.hpp>
13650
13651// #include <nlohmann/detail/meta/type_traits.hpp>
13652
13653// #include <nlohmann/detail/value_t.hpp>
13654
13655
13657namespace detail
13658{
13659
13660// forward declare to be able to friend it later on
13661template<typename IteratorType> class iteration_proxy;
13662template<typename IteratorType> class iteration_proxy_value;
13663
13680template<typename BasicJsonType>
13681class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13682{
13684 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13686 friend other_iter_impl;
13687 friend BasicJsonType;
13690
13691 using object_t = typename BasicJsonType::object_t;
13692 using array_t = typename BasicJsonType::array_t;
13693 // make sure BasicJsonType is basic_json or const basic_json
13695 "iter_impl only accepts (const) basic_json");
13696 // superficial check for the LegacyBidirectionalIterator named requirement
13697 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13698 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13699 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13700
13701 public:
13707 using iterator_category = std::bidirectional_iterator_tag;
13708
13710 using value_type = typename BasicJsonType::value_type;
13712 using difference_type = typename BasicJsonType::difference_type;
13714 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13715 typename BasicJsonType::const_pointer,
13716 typename BasicJsonType::pointer>::type;
13719 typename std::conditional<std::is_const<BasicJsonType>::value,
13720 typename BasicJsonType::const_reference,
13721 typename BasicJsonType::reference>::type;
13722
13723 iter_impl() = default;
13724 ~iter_impl() = default;
13725 iter_impl(iter_impl&&) noexcept = default;
13726 iter_impl& operator=(iter_impl&&) noexcept = default;
13727
13734 explicit iter_impl(pointer object) noexcept : m_object(object)
13735 {
13736 JSON_ASSERT(m_object != nullptr);
13737
13738 switch (m_object->m_data.m_type)
13739 {
13740 case value_t::object:
13741 {
13742 m_it.object_iterator = typename object_t::iterator();
13743 break;
13744 }
13745
13746 case value_t::array:
13747 {
13748 m_it.array_iterator = typename array_t::iterator();
13749 break;
13750 }
13751
13752 case value_t::null:
13753 case value_t::string:
13754 case value_t::boolean:
13758 case value_t::binary:
13759 case value_t::discarded:
13760 default:
13761 {
13762 m_it.primitive_iterator = primitive_iterator_t();
13763 break;
13764 }
13765 }
13766 }
13767
13776
13785 : m_object(other.m_object), m_it(other.m_it)
13786 {}
13787
13795 {
13796 if (&other != this)
13797 {
13798 m_object = other.m_object;
13799 m_it = other.m_it;
13800 }
13801 return *this;
13802 }
13803
13809 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13810 : m_object(other.m_object), m_it(other.m_it)
13811 {}
13812
13819 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13820 {
13821 m_object = other.m_object;
13822 m_it = other.m_it;
13823 return *this;
13824 }
13825
13831 void set_begin() noexcept
13832 {
13833 JSON_ASSERT(m_object != nullptr);
13834
13835 switch (m_object->m_data.m_type)
13836 {
13837 case value_t::object:
13838 {
13839 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13840 break;
13841 }
13842
13843 case value_t::array:
13844 {
13845 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13846 break;
13847 }
13848
13849 case value_t::null:
13850 {
13851 // set to end so begin()==end() is true: null is empty
13852 m_it.primitive_iterator.set_end();
13853 break;
13854 }
13855
13856 case value_t::string:
13857 case value_t::boolean:
13861 case value_t::binary:
13862 case value_t::discarded:
13863 default:
13864 {
13865 m_it.primitive_iterator.set_begin();
13866 break;
13867 }
13868 }
13869 }
13870
13875 void set_end() noexcept
13876 {
13877 JSON_ASSERT(m_object != nullptr);
13878
13879 switch (m_object->m_data.m_type)
13880 {
13881 case value_t::object:
13882 {
13883 m_it.object_iterator = m_object->m_data.m_value.object->end();
13884 break;
13885 }
13886
13887 case value_t::array:
13888 {
13889 m_it.array_iterator = m_object->m_data.m_value.array->end();
13890 break;
13891 }
13892
13893 case value_t::null:
13894 case value_t::string:
13895 case value_t::boolean:
13899 case value_t::binary:
13900 case value_t::discarded:
13901 default:
13902 {
13903 m_it.primitive_iterator.set_end();
13904 break;
13905 }
13906 }
13907 }
13908
13909 public:
13915 {
13916 JSON_ASSERT(m_object != nullptr);
13917
13918 switch (m_object->m_data.m_type)
13919 {
13920 case value_t::object:
13921 {
13922 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13923 return m_it.object_iterator->second;
13924 }
13925
13926 case value_t::array:
13927 {
13928 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13929 return *m_it.array_iterator;
13930 }
13931
13932 case value_t::null:
13933 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13934
13935 case value_t::string:
13936 case value_t::boolean:
13940 case value_t::binary:
13941 case value_t::discarded:
13942 default:
13943 {
13944 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13945 {
13946 return *m_object;
13947 }
13948
13949 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13950 }
13951 }
13952 }
13953
13959 {
13960 JSON_ASSERT(m_object != nullptr);
13961
13962 switch (m_object->m_data.m_type)
13963 {
13964 case value_t::object:
13965 {
13966 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13967 return &(m_it.object_iterator->second);
13968 }
13969
13970 case value_t::array:
13971 {
13972 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13973 return &*m_it.array_iterator;
13974 }
13975
13976 case value_t::null:
13977 case value_t::string:
13978 case value_t::boolean:
13982 case value_t::binary:
13983 case value_t::discarded:
13984 default:
13985 {
13986 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13987 {
13988 return m_object;
13989 }
13990
13991 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13992 }
13993 }
13994 }
13995
14000 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
14001 {
14002 auto result = *this;
14003 ++(*this);
14004 return result;
14005 }
14006
14012 {
14013 JSON_ASSERT(m_object != nullptr);
14014
14015 switch (m_object->m_data.m_type)
14016 {
14017 case value_t::object:
14018 {
14019 std::advance(m_it.object_iterator, 1);
14020 break;
14021 }
14022
14023 case value_t::array:
14024 {
14025 std::advance(m_it.array_iterator, 1);
14026 break;
14027 }
14028
14029 case value_t::null:
14030 case value_t::string:
14031 case value_t::boolean:
14035 case value_t::binary:
14036 case value_t::discarded:
14037 default:
14038 {
14039 ++m_it.primitive_iterator;
14040 break;
14041 }
14042 }
14043
14044 return *this;
14045 }
14046
14051 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
14052 {
14053 auto result = *this;
14054 --(*this);
14055 return result;
14056 }
14057
14063 {
14064 JSON_ASSERT(m_object != nullptr);
14065
14066 switch (m_object->m_data.m_type)
14067 {
14068 case value_t::object:
14069 {
14070 std::advance(m_it.object_iterator, -1);
14071 break;
14072 }
14073
14074 case value_t::array:
14075 {
14076 std::advance(m_it.array_iterator, -1);
14077 break;
14078 }
14079
14080 case value_t::null:
14081 case value_t::string:
14082 case value_t::boolean:
14086 case value_t::binary:
14087 case value_t::discarded:
14088 default:
14089 {
14090 --m_it.primitive_iterator;
14091 break;
14092 }
14093 }
14094
14095 return *this;
14096 }
14097
14102 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
14103 bool operator==(const IterImpl& other) const
14104 {
14105 // if objects are not the same, the comparison is undefined
14106 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14107 {
14108 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14109 }
14110
14111 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14112 if (m_object == nullptr)
14113 {
14114 return true;
14115 }
14116
14117 switch (m_object->m_data.m_type)
14118 {
14119 case value_t::object:
14120 return (m_it.object_iterator == other.m_it.object_iterator);
14121
14122 case value_t::array:
14123 return (m_it.array_iterator == other.m_it.array_iterator);
14124
14125 case value_t::null:
14126 case value_t::string:
14127 case value_t::boolean:
14131 case value_t::binary:
14132 case value_t::discarded:
14133 default:
14134 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
14135 }
14136 }
14137
14142 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
14143 bool operator!=(const IterImpl& other) const
14144 {
14145 return !operator==(other);
14146 }
14147
14152 bool operator<(const iter_impl& other) const
14153 {
14154 // if objects are not the same, the comparison is undefined
14155 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14156 {
14157 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14158 }
14159
14160 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14161 if (m_object == nullptr)
14162 {
14163 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
14164 return false;
14165 }
14166
14167 switch (m_object->m_data.m_type)
14168 {
14169 case value_t::object:
14170 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
14171
14172 case value_t::array:
14173 return (m_it.array_iterator < other.m_it.array_iterator);
14174
14175 case value_t::null:
14176 case value_t::string:
14177 case value_t::boolean:
14181 case value_t::binary:
14182 case value_t::discarded:
14183 default:
14184 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
14185 }
14186 }
14187
14192 bool operator<=(const iter_impl& other) const
14193 {
14194 return !other.operator < (*this);
14195 }
14196
14201 bool operator>(const iter_impl& other) const
14202 {
14203 return !operator<=(other);
14204 }
14205
14210 bool operator>=(const iter_impl& other) const
14211 {
14212 return !operator<(other);
14213 }
14214
14220 {
14221 JSON_ASSERT(m_object != nullptr);
14222
14223 switch (m_object->m_data.m_type)
14224 {
14225 case value_t::object:
14226 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14227
14228 case value_t::array:
14229 {
14230 std::advance(m_it.array_iterator, i);
14231 break;
14232 }
14233
14234 case value_t::null:
14235 case value_t::string:
14236 case value_t::boolean:
14240 case value_t::binary:
14241 case value_t::discarded:
14242 default:
14243 {
14244 m_it.primitive_iterator += i;
14245 break;
14246 }
14247 }
14248
14249 return *this;
14250 }
14251
14257 {
14258 return operator+=(-i);
14259 }
14260
14266 {
14267 auto result = *this;
14268 result += i;
14269 return result;
14270 }
14271
14277 {
14278 auto result = it;
14279 result += i;
14280 return result;
14281 }
14282
14288 {
14289 auto result = *this;
14290 result -= i;
14291 return result;
14292 }
14293
14299 {
14300 JSON_ASSERT(m_object != nullptr);
14301
14302 switch (m_object->m_data.m_type)
14303 {
14304 case value_t::object:
14305 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14306
14307 case value_t::array:
14308 return m_it.array_iterator - other.m_it.array_iterator;
14309
14310 case value_t::null:
14311 case value_t::string:
14312 case value_t::boolean:
14316 case value_t::binary:
14317 case value_t::discarded:
14318 default:
14319 return m_it.primitive_iterator - other.m_it.primitive_iterator;
14320 }
14321 }
14322
14328 {
14329 JSON_ASSERT(m_object != nullptr);
14330
14331 switch (m_object->m_data.m_type)
14332 {
14333 case value_t::object:
14334 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
14335
14336 case value_t::array:
14337 return *std::next(m_it.array_iterator, n);
14338
14339 case value_t::null:
14340 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14341
14342 case value_t::string:
14343 case value_t::boolean:
14347 case value_t::binary:
14348 case value_t::discarded:
14349 default:
14350 {
14351 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
14352 {
14353 return *m_object;
14354 }
14355
14356 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14357 }
14358 }
14359 }
14360
14365 const typename object_t::key_type& key() const
14366 {
14367 JSON_ASSERT(m_object != nullptr);
14368
14369 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
14370 {
14371 return m_it.object_iterator->first;
14372 }
14373
14374 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
14375 }
14376
14382 {
14383 return operator*();
14384 }
14385
14388 pointer m_object = nullptr;
14391};
14392
14393} // namespace detail
14395
14396// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
14397
14398// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
14399// __ _____ _____ _____
14400// __| | __| | | | JSON for Modern C++
14401// | | |__ | | | | | | version 3.12.0
14402// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14403//
14404// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14405// SPDX-License-Identifier: MIT
14406
14407
14408
14409#include <cstddef> // ptrdiff_t
14410#include <iterator> // reverse_iterator
14411#include <utility> // declval
14412
14413// #include <nlohmann/detail/abi_macros.hpp>
14414
14415
14417namespace detail
14418{
14419
14421// reverse_iterator //
14423
14442template<typename Base>
14443class json_reverse_iterator : public std::reverse_iterator<Base>
14444{
14445 public:
14446 using difference_type = std::ptrdiff_t;
14448 using base_iterator = std::reverse_iterator<Base>;
14450 using reference = typename Base::reference;
14451
14453 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
14454 : base_iterator(it) {}
14455
14457 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
14458
14460 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
14461 {
14462 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
14463 }
14464
14467 {
14468 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
14469 }
14470
14472 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
14473 {
14474 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
14475 }
14476
14479 {
14480 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
14481 }
14482
14485 {
14486 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
14487 }
14488
14491 {
14492 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
14493 }
14494
14497 {
14498 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
14499 }
14500
14503 {
14504 return base_iterator(*this) - base_iterator(other);
14505 }
14506
14509 {
14510 return *(this->operator+(n));
14511 }
14512
14514 auto key() const -> decltype(std::declval<Base>().key())
14515 {
14516 auto it = --this->base();
14517 return it.key();
14518 }
14519
14522 {
14523 auto it = --this->base();
14524 return it.operator * ();
14525 }
14526};
14527
14528} // namespace detail
14530
14531// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
14532
14533// #include <nlohmann/detail/json_custom_base_class.hpp>
14534// __ _____ _____ _____
14535// __| | __| | | | JSON for Modern C++
14536// | | |__ | | | | | | version 3.12.0
14537// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14538//
14539// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14540// SPDX-License-Identifier: MIT
14541
14542
14543
14544#include <type_traits> // conditional, is_same
14545
14546// #include <nlohmann/detail/abi_macros.hpp>
14547
14548
14550namespace detail
14551{
14552
14564
14565template<class T>
14566using json_base_class = typename std::conditional <
14567 std::is_same<T, void>::value,
14569 T
14570 >::type;
14571
14572} // namespace detail
14574
14575// #include <nlohmann/detail/json_pointer.hpp>
14576// __ _____ _____ _____
14577// __| | __| | | | JSON for Modern C++
14578// | | |__ | | | | | | version 3.12.0
14579// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14580//
14581// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14582// SPDX-License-Identifier: MIT
14583
14584
14585
14586#include <algorithm> // all_of
14587#include <cctype> // isdigit
14588#include <cerrno> // errno, ERANGE
14589#include <cstdlib> // strtoull
14590#ifndef JSON_NO_IO
14591 #include <iosfwd> // ostream
14592#endif // JSON_NO_IO
14593#include <limits> // max
14594#include <numeric> // accumulate
14595#include <string> // string
14596#include <utility> // move
14597#include <vector> // vector
14598
14599// #include <nlohmann/detail/exceptions.hpp>
14600
14601// #include <nlohmann/detail/macro_scope.hpp>
14602
14603// #include <nlohmann/detail/string_concat.hpp>
14604
14605// #include <nlohmann/detail/string_escape.hpp>
14606
14607// #include <nlohmann/detail/value_t.hpp>
14608
14609
14611
14614template<typename RefStringType>
14616{
14617 // allow basic_json to access private members
14619 friend class basic_json;
14620
14621 template<typename>
14622 friend class json_pointer;
14623
14624 template<typename T>
14625 struct string_t_helper
14626 {
14627 using type = T;
14628 };
14629
14631 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
14632 {
14633 using type = StringType;
14634 };
14635
14636 public:
14637 // for backwards compatibility accept BasicJsonType
14638 using string_t = typename string_t_helper<RefStringType>::type;
14639
14642 explicit json_pointer(const string_t& s = "")
14643 : reference_tokens(split(s))
14644 {}
14645
14649 {
14650 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14651 string_t{},
14652 [](const string_t& a, const string_t& b)
14653 {
14654 return detail::concat(a, '/', detail::escape(b));
14655 });
14656 }
14657
14661 operator string_t() const
14662 {
14663 return to_string();
14664 }
14665
14666#ifndef JSON_NO_IO
14669 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14670 {
14671 o << ptr.to_string();
14672 return o;
14673 }
14674#endif
14675
14679 {
14680 reference_tokens.insert(reference_tokens.end(),
14681 ptr.reference_tokens.begin(),
14682 ptr.reference_tokens.end());
14683 return *this;
14684 }
14685
14689 {
14690 push_back(std::move(token));
14691 return *this;
14692 }
14693
14696 json_pointer& operator/=(std::size_t array_idx)
14697 {
14698 return *this /= std::to_string(array_idx);
14699 }
14700
14704 const json_pointer& rhs)
14705 {
14706 return json_pointer(lhs) /= rhs;
14707 }
14708
14711 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14712 {
14713 return json_pointer(lhs) /= std::move(token);
14714 }
14715
14718 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14719 {
14720 return json_pointer(lhs) /= array_idx;
14721 }
14722
14726 {
14727 if (empty())
14728 {
14729 return *this;
14730 }
14731
14732 json_pointer res = *this;
14733 res.pop_back();
14734 return res;
14735 }
14736
14740 {
14742 {
14743 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14744 }
14745
14746 reference_tokens.pop_back();
14747 }
14748
14751 const string_t& back() const
14752 {
14754 {
14755 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14756 }
14757
14758 return reference_tokens.back();
14759 }
14760
14763 void push_back(const string_t& token)
14764 {
14765 reference_tokens.push_back(token);
14766 }
14767
14770 void push_back(string_t&& token)
14771 {
14772 reference_tokens.push_back(std::move(token));
14773 }
14774
14777 bool empty() const noexcept
14778 {
14779 return reference_tokens.empty();
14780 }
14781
14782 private:
14793 template<typename BasicJsonType>
14794 static typename BasicJsonType::size_type array_index(const string_t& s)
14795 {
14796 using size_type = typename BasicJsonType::size_type;
14797
14798 // error condition (cf. RFC 6901, Sect. 4)
14799 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14800 {
14801 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14802 }
14803
14804 // error condition (cf. RFC 6901, Sect. 4)
14805 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14806 {
14807 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14808 }
14809
14810 const char* p = s.c_str();
14811 char* p_end = nullptr; // NOLINT(misc-const-correctness)
14812 errno = 0; // strtoull doesn't reset errno
14813 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14814 if (p == p_end // invalid input or empty string
14815 || errno == ERANGE // out of range
14816 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14817 {
14818 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14819 }
14820
14821 // only triggered on special platforms (like 32bit), see also
14822 // https://github.com/nlohmann/json/pull/2203
14823 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14824 {
14825 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14826 }
14827
14828 return static_cast<size_type>(res);
14829 }
14830
14832 json_pointer top() const
14833 {
14834 if (JSON_HEDLEY_UNLIKELY(empty()))
14835 {
14836 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14837 }
14838
14839 json_pointer result = *this;
14840 result.reference_tokens = {reference_tokens[0]};
14841 return result;
14842 }
14843
14844 private:
14853 template<typename BasicJsonType>
14854 BasicJsonType& get_and_create(BasicJsonType& j) const
14855 {
14856 auto* result = &j;
14857
14858 // in case no reference tokens exist, return a reference to the JSON value
14859 // j which will be overwritten by a primitive value
14860 for (const auto& reference_token : reference_tokens)
14861 {
14862 switch (result->type())
14863 {
14865 {
14866 if (reference_token == "0")
14867 {
14868 // start a new array if the reference token is 0
14869 result = &result->operator[](0);
14870 }
14871 else
14872 {
14873 // start a new object otherwise
14874 result = &result->operator[](reference_token);
14875 }
14876 break;
14877 }
14878
14880 {
14881 // create an entry in the object
14882 result = &result->operator[](reference_token);
14883 break;
14884 }
14885
14887 {
14888 // create an entry in the array
14889 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14890 break;
14891 }
14892
14893 /*
14894 The following code is only reached if there exists a reference
14895 token _and_ the current value is primitive. In this case, we have
14896 an error situation, because primitive values may only occur as
14897 a single value; that is, with an empty list of reference tokens.
14898 */
14906 default:
14907 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14908 }
14909 }
14910
14911 return *result;
14912 }
14913
14933 template<typename BasicJsonType>
14934 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14935 {
14936 for (const auto& reference_token : reference_tokens)
14937 {
14938 // convert null values to arrays or objects before continuing
14939 if (ptr->is_null())
14940 {
14941 // check if the reference token is a number
14942 const bool nums =
14943 std::all_of(reference_token.begin(), reference_token.end(),
14944 [](const unsigned char x)
14945 {
14946 return std::isdigit(x);
14947 });
14948
14949 // change value to an array for numbers or "-" or to object otherwise
14950 *ptr = (nums || reference_token == "-")
14952 : detail::value_t::object;
14953 }
14954
14955 switch (ptr->type())
14956 {
14958 {
14959 // use unchecked object access
14960 ptr = &ptr->operator[](reference_token);
14961 break;
14962 }
14963
14965 {
14966 if (reference_token == "-")
14967 {
14968 // explicitly treat "-" as index beyond the end
14969 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14970 }
14971 else
14972 {
14973 // convert array index to number; unchecked access
14974 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14975 }
14976 break;
14977 }
14978
14987 default:
14988 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14989 }
14990 }
14991
14992 return *ptr;
14993 }
14994
15001 template<typename BasicJsonType>
15002 BasicJsonType& get_checked(BasicJsonType* ptr) const
15003 {
15004 for (const auto& reference_token : reference_tokens)
15005 {
15006 switch (ptr->type())
15007 {
15009 {
15010 // note: at performs range check
15011 ptr = &ptr->at(reference_token);
15012 break;
15013 }
15014
15016 {
15017 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15018 {
15019 // "-" always fails the range check
15021 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15022 ") is out of range"), ptr));
15023 }
15024
15025 // note: at performs range check
15026 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15027 break;
15028 }
15029
15038 default:
15039 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15040 }
15041 }
15042
15043 return *ptr;
15044 }
15045
15059 template<typename BasicJsonType>
15060 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
15061 {
15062 for (const auto& reference_token : reference_tokens)
15063 {
15064 switch (ptr->type())
15065 {
15067 {
15068 // use unchecked object access
15069 ptr = &ptr->operator[](reference_token);
15070 break;
15071 }
15072
15074 {
15075 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15076 {
15077 // "-" cannot be used for const access
15078 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
15079 }
15080
15081 // use unchecked array access
15082 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
15083 break;
15084 }
15085
15094 default:
15095 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15096 }
15097 }
15098
15099 return *ptr;
15100 }
15101
15108 template<typename BasicJsonType>
15109 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
15110 {
15111 for (const auto& reference_token : reference_tokens)
15112 {
15113 switch (ptr->type())
15114 {
15116 {
15117 // note: at performs range check
15118 ptr = &ptr->at(reference_token);
15119 break;
15120 }
15121
15123 {
15124 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15125 {
15126 // "-" always fails the range check
15128 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15129 ") is out of range"), ptr));
15130 }
15131
15132 // note: at performs range check
15133 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15134 break;
15135 }
15136
15145 default:
15146 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15147 }
15148 }
15149
15150 return *ptr;
15151 }
15152
15157 template<typename BasicJsonType>
15158 bool contains(const BasicJsonType* ptr) const
15159 {
15160 for (const auto& reference_token : reference_tokens)
15161 {
15162 switch (ptr->type())
15163 {
15165 {
15166 if (!ptr->contains(reference_token))
15167 {
15168 // we did not find the key in the object
15169 return false;
15170 }
15171
15172 ptr = &ptr->operator[](reference_token);
15173 break;
15174 }
15175
15177 {
15178 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15179 {
15180 // "-" always fails the range check
15181 return false;
15182 }
15183 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
15184 {
15185 // invalid char
15186 return false;
15187 }
15188 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
15189 {
15190 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
15191 {
15192 // the first char should be between '1' and '9'
15193 return false;
15194 }
15195 for (std::size_t i = 1; i < reference_token.size(); i++)
15196 {
15197 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
15198 {
15199 // other char should be between '0' and '9'
15200 return false;
15201 }
15202 }
15203 }
15204
15205 const auto idx = array_index<BasicJsonType>(reference_token);
15206 if (idx >= ptr->size())
15207 {
15208 // index out of range
15209 return false;
15210 }
15211
15212 ptr = &ptr->operator[](idx);
15213 break;
15214 }
15215
15224 default:
15225 {
15226 // we do not expect primitive values if there is still a
15227 // reference token to process
15228 return false;
15229 }
15230 }
15231 }
15232
15233 // no reference token left means we found a primitive value
15234 return true;
15235 }
15236
15246 static std::vector<string_t> split(const string_t& reference_string)
15247 {
15248 std::vector<string_t> result;
15249
15250 // special case: empty reference string -> no reference tokens
15251 if (reference_string.empty())
15252 {
15253 return result;
15254 }
15255
15256 // check if a nonempty reference string begins with slash
15257 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
15258 {
15259 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
15260 }
15261
15262 // extract the reference tokens:
15263 // - slash: position of the last read slash (or end of string)
15264 // - start: position after the previous slash
15265 for (
15266 // search for the first slash after the first character
15267 std::size_t slash = reference_string.find_first_of('/', 1),
15268 // set the beginning of the first reference token
15269 start = 1;
15270 // we can stop if start == 0 (if slash == string_t::npos)
15271 start != 0;
15272 // set the beginning of the next reference token
15273 // (will eventually be 0 if slash == string_t::npos)
15274 start = (slash == string_t::npos) ? 0 : slash + 1,
15275 // find next slash
15276 slash = reference_string.find_first_of('/', start))
15277 {
15278 // use the text between the beginning of the reference token
15279 // (start) and the last slash (slash).
15280 auto reference_token = reference_string.substr(start, slash - start);
15281
15282 // check reference tokens are properly escaped
15283 for (std::size_t pos = reference_token.find_first_of('~');
15284 pos != string_t::npos;
15285 pos = reference_token.find_first_of('~', pos + 1))
15286 {
15287 JSON_ASSERT(reference_token[pos] == '~');
15288
15289 // ~ must be followed by 0 or 1
15290 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
15291 (reference_token[pos + 1] != '0' &&
15292 reference_token[pos + 1] != '1')))
15293 {
15294 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
15295 }
15296 }
15297
15298 // finally, store the reference token
15299 detail::unescape(reference_token);
15300 result.push_back(reference_token);
15301 }
15302
15303 return result;
15304 }
15305
15306 private:
15314 template<typename BasicJsonType>
15315 static void flatten(const string_t& reference_string,
15316 const BasicJsonType& value,
15317 BasicJsonType& result)
15318 {
15319 switch (value.type())
15320 {
15322 {
15323 if (value.m_data.m_value.array->empty())
15324 {
15325 // flatten empty array as null
15326 result[reference_string] = nullptr;
15327 }
15328 else
15329 {
15330 // iterate array and use index as a reference string
15331 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
15332 {
15333 flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
15334 value.m_data.m_value.array->operator[](i), result);
15335 }
15336 }
15337 break;
15338 }
15339
15341 {
15342 if (value.m_data.m_value.object->empty())
15343 {
15344 // flatten empty object as null
15345 result[reference_string] = nullptr;
15346 }
15347 else
15348 {
15349 // iterate object and use keys as reference string
15350 for (const auto& element : *value.m_data.m_value.object)
15351 {
15352 flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
15353 }
15354 }
15355 break;
15356 }
15357
15366 default:
15367 {
15368 // add a primitive value with its reference string
15369 result[reference_string] = value;
15370 break;
15371 }
15372 }
15373 }
15374
15385 template<typename BasicJsonType>
15386 static BasicJsonType
15387 unflatten(const BasicJsonType& value)
15388 {
15389 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
15390 {
15391 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
15392 }
15393
15394 BasicJsonType result;
15395
15396 // iterate the JSON object values
15397 for (const auto& element : *value.m_data.m_value.object)
15398 {
15399 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
15400 {
15401 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
15402 }
15403
15404 // Assign the value to the reference pointed to by JSON pointer. Note
15405 // that if the JSON pointer is "" (i.e., points to the whole value),
15406 // function get_and_create returns a reference to the result itself.
15407 // An assignment will then create a primitive value.
15408 json_pointer(element.first).get_and_create(result) = element.second;
15409 }
15410
15411 return result;
15412 }
15413
15414 // can't use the conversion operator because of ambiguity
15415 json_pointer<string_t> convert() const&
15416 {
15417 json_pointer<string_t> result;
15418 result.reference_tokens = reference_tokens;
15419 return result;
15420 }
15421
15422 json_pointer<string_t> convert()&&
15423 {
15424 json_pointer<string_t> result;
15425 result.reference_tokens = std::move(reference_tokens);
15426 return result;
15427 }
15428
15429 public:
15430#if JSON_HAS_THREE_WAY_COMPARISON
15433 template<typename RefStringTypeRhs>
15434 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
15435 {
15436 return reference_tokens == rhs.reference_tokens;
15437 }
15438
15441 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
15442 bool operator==(const string_t& rhs) const
15443 {
15444 return *this == json_pointer(rhs);
15445 }
15446
15448 template<typename RefStringTypeRhs>
15449 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
15450 {
15451 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
15452 }
15453#else
15456 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15457 // NOLINTNEXTLINE(readability-redundant-declaration)
15458 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15459 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15460
15463 template<typename RefStringTypeLhs, typename StringType>
15464 // NOLINTNEXTLINE(readability-redundant-declaration)
15465 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15466 const StringType& rhs);
15467
15470 template<typename RefStringTypeRhs, typename StringType>
15471 // NOLINTNEXTLINE(readability-redundant-declaration)
15472 friend bool operator==(const StringType& lhs,
15473 const json_pointer<RefStringTypeRhs>& rhs);
15474
15477 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15478 // NOLINTNEXTLINE(readability-redundant-declaration)
15479 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15480 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15481
15484 template<typename RefStringTypeLhs, typename StringType>
15485 // NOLINTNEXTLINE(readability-redundant-declaration)
15486 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15487 const StringType& rhs);
15488
15491 template<typename RefStringTypeRhs, typename StringType>
15492 // NOLINTNEXTLINE(readability-redundant-declaration)
15493 friend bool operator!=(const StringType& lhs,
15494 const json_pointer<RefStringTypeRhs>& rhs);
15495
15497 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15498 // NOLINTNEXTLINE(readability-redundant-declaration)
15499 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15500 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15501#endif
15502
15503 private:
15505 std::vector<string_t> reference_tokens;
15506};
15507
15508#if !JSON_HAS_THREE_WAY_COMPARISON
15509// functions cannot be defined inside the class due to ODR violations
15510template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15512 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15513{
15514 return lhs.reference_tokens == rhs.reference_tokens;
15515}
15516
15517template<typename RefStringTypeLhs,
15518 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15520inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15521 const StringType& rhs)
15522{
15523 return lhs == json_pointer<RefStringTypeLhs>(rhs);
15524}
15525
15526template<typename RefStringTypeRhs,
15527 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15529inline bool operator==(const StringType& lhs,
15530 const json_pointer<RefStringTypeRhs>& rhs)
15531{
15532 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
15533}
15534
15535template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15537 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15538{
15539 return !(lhs == rhs);
15540}
15541
15542template<typename RefStringTypeLhs,
15543 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15545inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15546 const StringType& rhs)
15547{
15548 return !(lhs == rhs);
15549}
15550
15551template<typename RefStringTypeRhs,
15552 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15554inline bool operator!=(const StringType& lhs,
15555 const json_pointer<RefStringTypeRhs>& rhs)
15556{
15557 return !(lhs == rhs);
15558}
15559
15560template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15562 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15563{
15564 return lhs.reference_tokens < rhs.reference_tokens;
15565}
15566#endif
15567
15569
15570// #include <nlohmann/detail/json_ref.hpp>
15571// __ _____ _____ _____
15572// __| | __| | | | JSON for Modern C++
15573// | | |__ | | | | | | version 3.12.0
15574// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15575//
15576// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15577// SPDX-License-Identifier: MIT
15578
15579
15580
15581#include <initializer_list>
15582#include <utility>
15583
15584// #include <nlohmann/detail/abi_macros.hpp>
15585
15586// #include <nlohmann/detail/meta/type_traits.hpp>
15587
15588
15590namespace detail
15591{
15592
15593template<typename BasicJsonType>
15595{
15596 public:
15597 using value_type = BasicJsonType;
15598
15600 : owned_value(std::move(value))
15601 {}
15602
15604 : value_ref(&value)
15605 {}
15606
15607 json_ref(std::initializer_list<json_ref> init)
15608 : owned_value(init)
15609 {}
15610
15611 template <
15612 class... Args,
15613 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15614 json_ref(Args && ... args)
15615 : owned_value(std::forward<Args>(args)...)
15616 {}
15617
15618 // class should be movable only
15619 json_ref(json_ref&&) noexcept = default;
15620 json_ref(const json_ref&) = delete;
15621 json_ref& operator=(const json_ref&) = delete;
15622 json_ref& operator=(json_ref&&) = delete;
15623 ~json_ref() = default;
15624
15626 {
15627 if (value_ref == nullptr)
15628 {
15629 return std::move(owned_value);
15630 }
15631 return *value_ref;
15632 }
15633
15634 value_type const& operator*() const
15635 {
15636 return value_ref ? *value_ref : owned_value;
15637 }
15638
15639 value_type const* operator->() const
15640 {
15641 return &** this;
15642 }
15643
15644 private:
15645 mutable value_type owned_value = nullptr;
15646 value_type const* value_ref = nullptr;
15647};
15648
15649} // namespace detail
15651
15652// #include <nlohmann/detail/macro_scope.hpp>
15653
15654// #include <nlohmann/detail/string_concat.hpp>
15655
15656// #include <nlohmann/detail/string_escape.hpp>
15657
15658// #include <nlohmann/detail/string_utils.hpp>
15659
15660// #include <nlohmann/detail/meta/cpp_future.hpp>
15661
15662// #include <nlohmann/detail/meta/type_traits.hpp>
15663
15664// #include <nlohmann/detail/output/binary_writer.hpp>
15665// __ _____ _____ _____
15666// __| | __| | | | JSON for Modern C++
15667// | | |__ | | | | | | version 3.12.0
15668// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15669//
15670// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15671// SPDX-License-Identifier: MIT
15672
15673
15674
15675#include <algorithm> // reverse
15676#include <array> // array
15677#include <map> // map
15678#include <cmath> // isnan, isinf
15679#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15680#include <cstring> // memcpy
15681#include <limits> // numeric_limits
15682#include <string> // string
15683#include <utility> // move
15684#include <vector> // vector
15685
15686// #include <nlohmann/detail/input/binary_reader.hpp>
15687
15688// #include <nlohmann/detail/macro_scope.hpp>
15689
15690// #include <nlohmann/detail/output/output_adapters.hpp>
15691// __ _____ _____ _____
15692// __| | __| | | | JSON for Modern C++
15693// | | |__ | | | | | | version 3.12.0
15694// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15695//
15696// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15697// SPDX-License-Identifier: MIT
15698
15699
15700
15701#include <algorithm> // copy
15702#include <cstddef> // size_t
15703#include <iterator> // back_inserter
15704#include <memory> // shared_ptr, make_shared
15705#include <string> // basic_string
15706#include <vector> // vector
15707
15708#ifndef JSON_NO_IO
15709 #include <ios> // streamsize
15710 #include <ostream> // basic_ostream
15711#endif // JSON_NO_IO
15712
15713// #include <nlohmann/detail/macro_scope.hpp>
15714
15715
15717namespace detail
15718{
15719
15721template<typename CharType> struct output_adapter_protocol
15722{
15723 virtual void write_character(CharType c) = 0;
15724 virtual void write_characters(const CharType* s, std::size_t length) = 0;
15725 virtual ~output_adapter_protocol() = default;
15726
15731 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15732};
15733
15735template<typename CharType>
15736using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15737
15739template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15741{
15742 public:
15743 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15744 : v(vec)
15745 {}
15746
15747 void write_character(CharType c) override
15748 {
15749 v.push_back(c);
15750 }
15751
15753 void write_characters(const CharType* s, std::size_t length) override
15754 {
15755 v.insert(v.end(), s, s + length);
15756 }
15757
15758 private:
15759 std::vector<CharType, AllocatorType>& v;
15760};
15761
15762#ifndef JSON_NO_IO
15764template<typename CharType>
15766{
15767 public:
15768 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15769 : stream(s)
15770 {}
15771
15772 void write_character(CharType c) override
15773 {
15774 stream.put(c);
15775 }
15776
15778 void write_characters(const CharType* s, std::size_t length) override
15779 {
15780 stream.write(s, static_cast<std::streamsize>(length));
15781 }
15782
15783 private:
15784 std::basic_ostream<CharType>& stream;
15785};
15786#endif // JSON_NO_IO
15787
15789template<typename CharType, typename StringType = std::basic_string<CharType>>
15791{
15792 public:
15793 explicit output_string_adapter(StringType& s) noexcept
15794 : str(s)
15795 {}
15796
15797 void write_character(CharType c) override
15798 {
15799 str.push_back(c);
15800 }
15801
15803 void write_characters(const CharType* s, std::size_t length) override
15804 {
15805 str.append(s, length);
15806 }
15807
15808 private:
15809 StringType& str;
15810};
15811
15812template<typename CharType, typename StringType = std::basic_string<CharType>>
15814{
15815 public:
15816 template<typename AllocatorType = std::allocator<CharType>>
15817 output_adapter(std::vector<CharType, AllocatorType>& vec)
15818 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15819
15820#ifndef JSON_NO_IO
15821 output_adapter(std::basic_ostream<CharType>& s)
15822 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15823#endif // JSON_NO_IO
15824
15825 output_adapter(StringType& s)
15826 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15827
15829 {
15830 return oa;
15831 }
15832
15833 private:
15834 output_adapter_t<CharType> oa = nullptr;
15835};
15836
15837} // namespace detail
15839
15840// #include <nlohmann/detail/string_concat.hpp>
15841
15842
15844namespace detail
15845{
15846
15849{
15852};
15853
15855// binary writer //
15857
15861template<typename BasicJsonType, typename CharType>
15863{
15864 using string_t = typename BasicJsonType::string_t;
15865 using binary_t = typename BasicJsonType::binary_t;
15866 using number_float_t = typename BasicJsonType::number_float_t;
15867
15868 public:
15874 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15875 {
15876 JSON_ASSERT(oa);
15877 }
15878
15883 void write_bson(const BasicJsonType& j)
15884 {
15885 switch (j.type())
15886 {
15887 case value_t::object:
15888 {
15889 write_bson_object(*j.m_data.m_value.object);
15890 break;
15891 }
15892
15893 case value_t::null:
15894 case value_t::array:
15895 case value_t::string:
15896 case value_t::boolean:
15900 case value_t::binary:
15901 case value_t::discarded:
15902 default:
15903 {
15904 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15905 }
15906 }
15907 }
15908
15912 void write_cbor(const BasicJsonType& j)
15913 {
15914 switch (j.type())
15915 {
15916 case value_t::null:
15917 {
15918 oa->write_character(to_char_type(0xF6));
15919 break;
15920 }
15921
15922 case value_t::boolean:
15923 {
15924 oa->write_character(j.m_data.m_value.boolean
15925 ? to_char_type(0xF5)
15926 : to_char_type(0xF4));
15927 break;
15928 }
15929
15931 {
15932 if (j.m_data.m_value.number_integer >= 0)
15933 {
15934 // CBOR does not differentiate between positive signed
15935 // integers and unsigned integers. Therefore, we used the
15936 // code from the value_t::number_unsigned case here.
15937 if (j.m_data.m_value.number_integer <= 0x17)
15938 {
15939 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15940 }
15941 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15942 {
15943 oa->write_character(to_char_type(0x18));
15944 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15945 }
15946 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15947 {
15948 oa->write_character(to_char_type(0x19));
15949 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15950 }
15951 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15952 {
15953 oa->write_character(to_char_type(0x1A));
15954 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15955 }
15956 else
15957 {
15958 oa->write_character(to_char_type(0x1B));
15959 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15960 }
15961 }
15962 else
15963 {
15964 // The conversions below encode the sign in the first
15965 // byte, and the value is converted to a positive number.
15966 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15967 if (j.m_data.m_value.number_integer >= -24)
15968 {
15969 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15970 }
15971 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15972 {
15973 oa->write_character(to_char_type(0x38));
15974 write_number(static_cast<std::uint8_t>(positive_number));
15975 }
15976 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15977 {
15978 oa->write_character(to_char_type(0x39));
15979 write_number(static_cast<std::uint16_t>(positive_number));
15980 }
15981 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15982 {
15983 oa->write_character(to_char_type(0x3A));
15984 write_number(static_cast<std::uint32_t>(positive_number));
15985 }
15986 else
15987 {
15988 oa->write_character(to_char_type(0x3B));
15989 write_number(static_cast<std::uint64_t>(positive_number));
15990 }
15991 }
15992 break;
15993 }
15994
15996 {
15997 if (j.m_data.m_value.number_unsigned <= 0x17)
15998 {
15999 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
16000 }
16001 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16002 {
16003 oa->write_character(to_char_type(0x18));
16004 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
16005 }
16006 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16007 {
16008 oa->write_character(to_char_type(0x19));
16009 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
16010 }
16011 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16012 {
16013 oa->write_character(to_char_type(0x1A));
16014 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
16015 }
16016 else
16017 {
16018 oa->write_character(to_char_type(0x1B));
16019 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
16020 }
16021 break;
16022 }
16023
16025 {
16026 if (std::isnan(j.m_data.m_value.number_float))
16027 {
16028 // NaN is 0xf97e00 in CBOR
16029 oa->write_character(to_char_type(0xF9));
16030 oa->write_character(to_char_type(0x7E));
16031 oa->write_character(to_char_type(0x00));
16032 }
16033 else if (std::isinf(j.m_data.m_value.number_float))
16034 {
16035 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
16036 oa->write_character(to_char_type(0xf9));
16037 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
16038 oa->write_character(to_char_type(0x00));
16039 }
16040 else
16041 {
16042 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
16043 }
16044 break;
16045 }
16046
16047 case value_t::string:
16048 {
16049 // step 1: write control byte and the string length
16050 const auto N = j.m_data.m_value.string->size();
16051 if (N <= 0x17)
16052 {
16053 write_number(static_cast<std::uint8_t>(0x60 + N));
16054 }
16055 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16056 {
16057 oa->write_character(to_char_type(0x78));
16058 write_number(static_cast<std::uint8_t>(N));
16059 }
16060 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16061 {
16062 oa->write_character(to_char_type(0x79));
16063 write_number(static_cast<std::uint16_t>(N));
16064 }
16065 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16066 {
16067 oa->write_character(to_char_type(0x7A));
16068 write_number(static_cast<std::uint32_t>(N));
16069 }
16070 // LCOV_EXCL_START
16071 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16072 {
16073 oa->write_character(to_char_type(0x7B));
16074 write_number(static_cast<std::uint64_t>(N));
16075 }
16076 // LCOV_EXCL_STOP
16077
16078 // step 2: write the string
16079 oa->write_characters(
16080 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16081 j.m_data.m_value.string->size());
16082 break;
16083 }
16084
16085 case value_t::array:
16086 {
16087 // step 1: write control byte and the array size
16088 const auto N = j.m_data.m_value.array->size();
16089 if (N <= 0x17)
16090 {
16091 write_number(static_cast<std::uint8_t>(0x80 + N));
16092 }
16093 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16094 {
16095 oa->write_character(to_char_type(0x98));
16096 write_number(static_cast<std::uint8_t>(N));
16097 }
16098 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16099 {
16100 oa->write_character(to_char_type(0x99));
16101 write_number(static_cast<std::uint16_t>(N));
16102 }
16103 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16104 {
16105 oa->write_character(to_char_type(0x9A));
16106 write_number(static_cast<std::uint32_t>(N));
16107 }
16108 // LCOV_EXCL_START
16109 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16110 {
16111 oa->write_character(to_char_type(0x9B));
16112 write_number(static_cast<std::uint64_t>(N));
16113 }
16114 // LCOV_EXCL_STOP
16115
16116 // step 2: write each element
16117 for (const auto& el : *j.m_data.m_value.array)
16118 {
16119 write_cbor(el);
16120 }
16121 break;
16122 }
16123
16124 case value_t::binary:
16125 {
16126 if (j.m_data.m_value.binary->has_subtype())
16127 {
16128 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
16129 {
16130 write_number(static_cast<std::uint8_t>(0xd8));
16131 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
16132 }
16133 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
16134 {
16135 write_number(static_cast<std::uint8_t>(0xd9));
16136 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
16137 }
16138 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
16139 {
16140 write_number(static_cast<std::uint8_t>(0xda));
16141 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
16142 }
16143 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
16144 {
16145 write_number(static_cast<std::uint8_t>(0xdb));
16146 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
16147 }
16148 }
16149
16150 // step 1: write control byte and the binary array size
16151 const auto N = j.m_data.m_value.binary->size();
16152 if (N <= 0x17)
16153 {
16154 write_number(static_cast<std::uint8_t>(0x40 + N));
16155 }
16156 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16157 {
16158 oa->write_character(to_char_type(0x58));
16159 write_number(static_cast<std::uint8_t>(N));
16160 }
16161 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16162 {
16163 oa->write_character(to_char_type(0x59));
16164 write_number(static_cast<std::uint16_t>(N));
16165 }
16166 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16167 {
16168 oa->write_character(to_char_type(0x5A));
16169 write_number(static_cast<std::uint32_t>(N));
16170 }
16171 // LCOV_EXCL_START
16172 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16173 {
16174 oa->write_character(to_char_type(0x5B));
16175 write_number(static_cast<std::uint64_t>(N));
16176 }
16177 // LCOV_EXCL_STOP
16178
16179 // step 2: write each element
16180 oa->write_characters(
16181 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16182 N);
16183
16184 break;
16185 }
16186
16187 case value_t::object:
16188 {
16189 // step 1: write control byte and the object size
16190 const auto N = j.m_data.m_value.object->size();
16191 if (N <= 0x17)
16192 {
16193 write_number(static_cast<std::uint8_t>(0xA0 + N));
16194 }
16195 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16196 {
16197 oa->write_character(to_char_type(0xB8));
16198 write_number(static_cast<std::uint8_t>(N));
16199 }
16200 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16201 {
16202 oa->write_character(to_char_type(0xB9));
16203 write_number(static_cast<std::uint16_t>(N));
16204 }
16205 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16206 {
16207 oa->write_character(to_char_type(0xBA));
16208 write_number(static_cast<std::uint32_t>(N));
16209 }
16210 // LCOV_EXCL_START
16211 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16212 {
16213 oa->write_character(to_char_type(0xBB));
16214 write_number(static_cast<std::uint64_t>(N));
16215 }
16216 // LCOV_EXCL_STOP
16217
16218 // step 2: write each element
16219 for (const auto& el : *j.m_data.m_value.object)
16220 {
16221 write_cbor(el.first);
16222 write_cbor(el.second);
16223 }
16224 break;
16225 }
16226
16227 case value_t::discarded:
16228 default:
16229 break;
16230 }
16231 }
16232
16236 void write_msgpack(const BasicJsonType& j)
16237 {
16238 switch (j.type())
16239 {
16240 case value_t::null: // nil
16241 {
16242 oa->write_character(to_char_type(0xC0));
16243 break;
16244 }
16245
16246 case value_t::boolean: // true and false
16247 {
16248 oa->write_character(j.m_data.m_value.boolean
16249 ? to_char_type(0xC3)
16250 : to_char_type(0xC2));
16251 break;
16252 }
16253
16255 {
16256 if (j.m_data.m_value.number_integer >= 0)
16257 {
16258 // MessagePack does not differentiate between positive
16259 // signed integers and unsigned integers. Therefore, we used
16260 // the code from the value_t::number_unsigned case here.
16261 if (j.m_data.m_value.number_unsigned < 128)
16262 {
16263 // positive fixnum
16264 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16265 }
16266 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16267 {
16268 // uint 8
16269 oa->write_character(to_char_type(0xCC));
16270 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16271 }
16272 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16273 {
16274 // uint 16
16275 oa->write_character(to_char_type(0xCD));
16276 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16277 }
16278 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16279 {
16280 // uint 32
16281 oa->write_character(to_char_type(0xCE));
16282 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16283 }
16284 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16285 {
16286 // uint 64
16287 oa->write_character(to_char_type(0xCF));
16288 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16289 }
16290 }
16291 else
16292 {
16293 if (j.m_data.m_value.number_integer >= -32)
16294 {
16295 // negative fixnum
16296 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16297 }
16298 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
16299 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16300 {
16301 // int 8
16302 oa->write_character(to_char_type(0xD0));
16303 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16304 }
16305 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
16306 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16307 {
16308 // int 16
16309 oa->write_character(to_char_type(0xD1));
16310 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
16311 }
16312 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
16313 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16314 {
16315 // int 32
16316 oa->write_character(to_char_type(0xD2));
16317 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
16318 }
16319 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
16320 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16321 {
16322 // int 64
16323 oa->write_character(to_char_type(0xD3));
16324 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
16325 }
16326 }
16327 break;
16328 }
16329
16331 {
16332 if (j.m_data.m_value.number_unsigned < 128)
16333 {
16334 // positive fixnum
16335 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16336 }
16337 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16338 {
16339 // uint 8
16340 oa->write_character(to_char_type(0xCC));
16341 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16342 }
16343 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16344 {
16345 // uint 16
16346 oa->write_character(to_char_type(0xCD));
16347 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16348 }
16349 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16350 {
16351 // uint 32
16352 oa->write_character(to_char_type(0xCE));
16353 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16354 }
16355 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16356 {
16357 // uint 64
16358 oa->write_character(to_char_type(0xCF));
16359 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16360 }
16361 break;
16362 }
16363
16365 {
16366 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
16367 break;
16368 }
16369
16370 case value_t::string:
16371 {
16372 // step 1: write control byte and the string length
16373 const auto N = j.m_data.m_value.string->size();
16374 if (N <= 31)
16375 {
16376 // fixstr
16377 write_number(static_cast<std::uint8_t>(0xA0 | N));
16378 }
16379 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16380 {
16381 // str 8
16382 oa->write_character(to_char_type(0xD9));
16383 write_number(static_cast<std::uint8_t>(N));
16384 }
16385 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16386 {
16387 // str 16
16388 oa->write_character(to_char_type(0xDA));
16389 write_number(static_cast<std::uint16_t>(N));
16390 }
16391 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16392 {
16393 // str 32
16394 oa->write_character(to_char_type(0xDB));
16395 write_number(static_cast<std::uint32_t>(N));
16396 }
16397
16398 // step 2: write the string
16399 oa->write_characters(
16400 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16401 j.m_data.m_value.string->size());
16402 break;
16403 }
16404
16405 case value_t::array:
16406 {
16407 // step 1: write control byte and the array size
16408 const auto N = j.m_data.m_value.array->size();
16409 if (N <= 15)
16410 {
16411 // fixarray
16412 write_number(static_cast<std::uint8_t>(0x90 | N));
16413 }
16414 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16415 {
16416 // array 16
16417 oa->write_character(to_char_type(0xDC));
16418 write_number(static_cast<std::uint16_t>(N));
16419 }
16420 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16421 {
16422 // array 32
16423 oa->write_character(to_char_type(0xDD));
16424 write_number(static_cast<std::uint32_t>(N));
16425 }
16426
16427 // step 2: write each element
16428 for (const auto& el : *j.m_data.m_value.array)
16429 {
16430 write_msgpack(el);
16431 }
16432 break;
16433 }
16434
16435 case value_t::binary:
16436 {
16437 // step 0: determine if the binary type has a set subtype to
16438 // determine whether to use the ext or fixext types
16439 const bool use_ext = j.m_data.m_value.binary->has_subtype();
16440
16441 // step 1: write control byte and the byte string length
16442 const auto N = j.m_data.m_value.binary->size();
16443 if (N <= (std::numeric_limits<std::uint8_t>::max)())
16444 {
16445 std::uint8_t output_type{};
16446 bool fixed = true;
16447 if (use_ext)
16448 {
16449 switch (N)
16450 {
16451 case 1:
16452 output_type = 0xD4; // fixext 1
16453 break;
16454 case 2:
16455 output_type = 0xD5; // fixext 2
16456 break;
16457 case 4:
16458 output_type = 0xD6; // fixext 4
16459 break;
16460 case 8:
16461 output_type = 0xD7; // fixext 8
16462 break;
16463 case 16:
16464 output_type = 0xD8; // fixext 16
16465 break;
16466 default:
16467 output_type = 0xC7; // ext 8
16468 fixed = false;
16469 break;
16470 }
16471
16472 }
16473 else
16474 {
16475 output_type = 0xC4; // bin 8
16476 fixed = false;
16477 }
16478
16479 oa->write_character(to_char_type(output_type));
16480 if (!fixed)
16481 {
16482 write_number(static_cast<std::uint8_t>(N));
16483 }
16484 }
16485 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16486 {
16487 const std::uint8_t output_type = use_ext
16488 ? 0xC8 // ext 16
16489 : 0xC5; // bin 16
16490
16491 oa->write_character(to_char_type(output_type));
16492 write_number(static_cast<std::uint16_t>(N));
16493 }
16494 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16495 {
16496 const std::uint8_t output_type = use_ext
16497 ? 0xC9 // ext 32
16498 : 0xC6; // bin 32
16499
16500 oa->write_character(to_char_type(output_type));
16501 write_number(static_cast<std::uint32_t>(N));
16502 }
16503
16504 // step 1.5: if this is an ext type, write the subtype
16505 if (use_ext)
16506 {
16507 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
16508 }
16509
16510 // step 2: write the byte string
16511 oa->write_characters(
16512 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16513 N);
16514
16515 break;
16516 }
16517
16518 case value_t::object:
16519 {
16520 // step 1: write control byte and the object size
16521 const auto N = j.m_data.m_value.object->size();
16522 if (N <= 15)
16523 {
16524 // fixmap
16525 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
16526 }
16527 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16528 {
16529 // map 16
16530 oa->write_character(to_char_type(0xDE));
16531 write_number(static_cast<std::uint16_t>(N));
16532 }
16533 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16534 {
16535 // map 32
16536 oa->write_character(to_char_type(0xDF));
16537 write_number(static_cast<std::uint32_t>(N));
16538 }
16539
16540 // step 2: write each element
16541 for (const auto& el : *j.m_data.m_value.object)
16542 {
16543 write_msgpack(el.first);
16544 write_msgpack(el.second);
16545 }
16546 break;
16547 }
16548
16549 case value_t::discarded:
16550 default:
16551 break;
16552 }
16553 }
16554
16563 void write_ubjson(const BasicJsonType& j, const bool use_count,
16564 const bool use_type, const bool add_prefix = true,
16565 const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
16566 {
16567 const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
16568
16569 switch (j.type())
16570 {
16571 case value_t::null:
16572 {
16573 if (add_prefix)
16574 {
16575 oa->write_character(to_char_type('Z'));
16576 }
16577 break;
16578 }
16579
16580 case value_t::boolean:
16581 {
16582 if (add_prefix)
16583 {
16584 oa->write_character(j.m_data.m_value.boolean
16585 ? to_char_type('T')
16586 : to_char_type('F'));
16587 }
16588 break;
16589 }
16590
16592 {
16593 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16594 break;
16595 }
16596
16598 {
16599 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16600 break;
16601 }
16602
16604 {
16605 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16606 break;
16607 }
16608
16609 case value_t::string:
16610 {
16611 if (add_prefix)
16612 {
16613 oa->write_character(to_char_type('S'));
16614 }
16615 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16616 oa->write_characters(
16617 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16618 j.m_data.m_value.string->size());
16619 break;
16620 }
16621
16622 case value_t::array:
16623 {
16624 if (add_prefix)
16625 {
16626 oa->write_character(to_char_type('['));
16627 }
16628
16629 bool prefix_required = true;
16630 if (use_type && !j.m_data.m_value.array->empty())
16631 {
16632 JSON_ASSERT(use_count);
16633 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16634 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16635 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16636 {
16637 return ubjson_prefix(v, use_bjdata) == first_prefix;
16638 });
16639
16640 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16641
16642 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16643 {
16644 prefix_required = false;
16645 oa->write_character(to_char_type('$'));
16646 oa->write_character(first_prefix);
16647 }
16648 }
16649
16650 if (use_count)
16651 {
16652 oa->write_character(to_char_type('#'));
16653 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16654 }
16655
16656 for (const auto& el : *j.m_data.m_value.array)
16657 {
16658 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16659 }
16660
16661 if (!use_count)
16662 {
16663 oa->write_character(to_char_type(']'));
16664 }
16665
16666 break;
16667 }
16668
16669 case value_t::binary:
16670 {
16671 if (add_prefix)
16672 {
16673 oa->write_character(to_char_type('['));
16674 }
16675
16676 if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
16677 {
16678 JSON_ASSERT(use_count);
16679 oa->write_character(to_char_type('$'));
16680 oa->write_character(bjdata_draft3 ? 'B' : 'U');
16681 }
16682
16683 if (use_count)
16684 {
16685 oa->write_character(to_char_type('#'));
16686 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16687 }
16688
16689 if (use_type)
16690 {
16691 oa->write_characters(
16692 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16693 j.m_data.m_value.binary->size());
16694 }
16695 else
16696 {
16697 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16698 {
16699 oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
16700 oa->write_character(j.m_data.m_value.binary->data()[i]);
16701 }
16702 }
16703
16704 if (!use_count)
16705 {
16706 oa->write_character(to_char_type(']'));
16707 }
16708
16709 break;
16710 }
16711
16712 case value_t::object:
16713 {
16714 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
16715 {
16716 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type, bjdata_version)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
16717 {
16718 break;
16719 }
16720 }
16721
16722 if (add_prefix)
16723 {
16724 oa->write_character(to_char_type('{'));
16725 }
16726
16727 bool prefix_required = true;
16728 if (use_type && !j.m_data.m_value.object->empty())
16729 {
16730 JSON_ASSERT(use_count);
16731 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16732 const bool same_prefix = std::all_of(j.begin(), j.end(),
16733 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16734 {
16735 return ubjson_prefix(v, use_bjdata) == first_prefix;
16736 });
16737
16738 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16739
16740 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16741 {
16742 prefix_required = false;
16743 oa->write_character(to_char_type('$'));
16744 oa->write_character(first_prefix);
16745 }
16746 }
16747
16748 if (use_count)
16749 {
16750 oa->write_character(to_char_type('#'));
16751 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16752 }
16753
16754 for (const auto& el : *j.m_data.m_value.object)
16755 {
16756 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16757 oa->write_characters(
16758 reinterpret_cast<const CharType*>(el.first.c_str()),
16759 el.first.size());
16760 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16761 }
16762
16763 if (!use_count)
16764 {
16765 oa->write_character(to_char_type('}'));
16766 }
16767
16768 break;
16769 }
16770
16771 case value_t::discarded:
16772 default:
16773 break;
16774 }
16775 }
16776
16777 private:
16779 // BSON //
16781
16786 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16787 {
16788 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16789 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16790 {
16791 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16792 }
16793
16794 static_cast<void>(j);
16795 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16796 }
16797
16801 void write_bson_entry_header(const string_t& name,
16802 const std::uint8_t element_type)
16803 {
16804 oa->write_character(to_char_type(element_type)); // boolean
16805 oa->write_characters(
16806 reinterpret_cast<const CharType*>(name.c_str()),
16807 name.size() + 1u);
16808 }
16809
16813 void write_bson_boolean(const string_t& name,
16814 const bool value)
16815 {
16816 write_bson_entry_header(name, 0x08);
16817 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16818 }
16819
16823 void write_bson_double(const string_t& name,
16824 const double value)
16825 {
16826 write_bson_entry_header(name, 0x01);
16827 write_number<double>(value, true);
16828 }
16829
16833 static std::size_t calc_bson_string_size(const string_t& value)
16834 {
16835 return sizeof(std::int32_t) + value.size() + 1ul;
16836 }
16837
16841 void write_bson_string(const string_t& name,
16842 const string_t& value)
16843 {
16844 write_bson_entry_header(name, 0x02);
16845
16846 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16847 oa->write_characters(
16848 reinterpret_cast<const CharType*>(value.c_str()),
16849 value.size() + 1);
16850 }
16851
16855 void write_bson_null(const string_t& name)
16856 {
16857 write_bson_entry_header(name, 0x0A);
16858 }
16859
16863 static std::size_t calc_bson_integer_size(const std::int64_t value)
16864 {
16865 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16866 ? sizeof(std::int32_t)
16867 : sizeof(std::int64_t);
16868 }
16869
16873 void write_bson_integer(const string_t& name,
16874 const std::int64_t value)
16875 {
16876 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16877 {
16878 write_bson_entry_header(name, 0x10); // int32
16879 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16880 }
16881 else
16882 {
16883 write_bson_entry_header(name, 0x12); // int64
16884 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16885 }
16886 }
16887
16891 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16892 {
16893 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16894 ? sizeof(std::int32_t)
16895 : sizeof(std::int64_t);
16896 }
16897
16901 void write_bson_unsigned(const string_t& name,
16902 const BasicJsonType& j)
16903 {
16904 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16905 {
16906 write_bson_entry_header(name, 0x10 /* int32 */);
16907 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16908 }
16909 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16910 {
16911 write_bson_entry_header(name, 0x12 /* int64 */);
16912 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16913 }
16914 else
16915 {
16916 write_bson_entry_header(name, 0x11 /* uint64 */);
16917 write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
16918 }
16919 }
16920
16924 void write_bson_object_entry(const string_t& name,
16925 const typename BasicJsonType::object_t& value)
16926 {
16927 write_bson_entry_header(name, 0x03); // object
16928 write_bson_object(value);
16929 }
16930
16934 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16935 {
16936 std::size_t array_index = 0ul;
16937
16938 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
16939 {
16940 return result + calc_bson_element_size(std::to_string(array_index++), el);
16941 });
16942
16943 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16944 }
16945
16949 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16950 {
16951 return sizeof(std::int32_t) + value.size() + 1ul;
16952 }
16953
16957 void write_bson_array(const string_t& name,
16958 const typename BasicJsonType::array_t& value)
16959 {
16960 write_bson_entry_header(name, 0x04); // array
16961 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16962
16963 std::size_t array_index = 0ul;
16964
16965 for (const auto& el : value)
16966 {
16967 write_bson_element(std::to_string(array_index++), el);
16968 }
16969
16970 oa->write_character(to_char_type(0x00));
16971 }
16972
16976 void write_bson_binary(const string_t& name,
16977 const binary_t& value)
16978 {
16979 write_bson_entry_header(name, 0x05);
16980
16981 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16982 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16983
16984 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16985 }
16986
16991 static std::size_t calc_bson_element_size(const string_t& name,
16992 const BasicJsonType& j)
16993 {
16994 const auto header_size = calc_bson_entry_header_size(name, j);
16995 switch (j.type())
16996 {
16997 case value_t::object:
16998 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16999
17000 case value_t::array:
17001 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
17002
17003 case value_t::binary:
17004 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
17005
17006 case value_t::boolean:
17007 return header_size + 1ul;
17008
17009 case value_t::number_float:
17010 return header_size + 8ul;
17011
17012 case value_t::number_integer:
17013 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
17014
17015 case value_t::number_unsigned:
17016 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
17017
17018 case value_t::string:
17019 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
17020
17021 case value_t::null:
17022 return header_size + 0ul;
17023
17024 // LCOV_EXCL_START
17025 case value_t::discarded:
17026 default:
17027 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17028 return 0ul;
17029 // LCOV_EXCL_STOP
17030 }
17031 }
17032
17039 void write_bson_element(const string_t& name,
17040 const BasicJsonType& j)
17041 {
17042 switch (j.type())
17043 {
17044 case value_t::object:
17045 return write_bson_object_entry(name, *j.m_data.m_value.object);
17046
17047 case value_t::array:
17048 return write_bson_array(name, *j.m_data.m_value.array);
17049
17050 case value_t::binary:
17051 return write_bson_binary(name, *j.m_data.m_value.binary);
17052
17053 case value_t::boolean:
17054 return write_bson_boolean(name, j.m_data.m_value.boolean);
17055
17056 case value_t::number_float:
17057 return write_bson_double(name, j.m_data.m_value.number_float);
17058
17059 case value_t::number_integer:
17060 return write_bson_integer(name, j.m_data.m_value.number_integer);
17061
17062 case value_t::number_unsigned:
17063 return write_bson_unsigned(name, j);
17064
17065 case value_t::string:
17066 return write_bson_string(name, *j.m_data.m_value.string);
17067
17068 case value_t::null:
17069 return write_bson_null(name);
17070
17071 // LCOV_EXCL_START
17072 case value_t::discarded:
17073 default:
17074 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17075 return;
17076 // LCOV_EXCL_STOP
17077 }
17078 }
17079
17086 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
17087 {
17088 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
17089 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
17090 {
17091 return result += calc_bson_element_size(el.first, el.second);
17092 });
17093
17094 return sizeof(std::int32_t) + document_size + 1ul;
17095 }
17096
17101 void write_bson_object(const typename BasicJsonType::object_t& value)
17102 {
17103 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
17104
17105 for (const auto& el : value)
17106 {
17107 write_bson_element(el.first, el.second);
17108 }
17109
17110 oa->write_character(to_char_type(0x00));
17111 }
17112
17114 // CBOR //
17116
17117 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
17118 {
17119 return to_char_type(0xFA); // Single-Precision Float
17120 }
17121
17122 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
17123 {
17124 return to_char_type(0xFB); // Double-Precision Float
17125 }
17126
17128 // MsgPack //
17130
17131 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
17132 {
17133 return to_char_type(0xCA); // float 32
17134 }
17135
17136 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
17137 {
17138 return to_char_type(0xCB); // float 64
17139 }
17140
17142 // UBJSON //
17144
17145 // UBJSON: write number (floating point)
17146 template<typename NumberType, typename std::enable_if<
17147 std::is_floating_point<NumberType>::value, int>::type = 0>
17148 void write_number_with_ubjson_prefix(const NumberType n,
17149 const bool add_prefix,
17150 const bool use_bjdata)
17151 {
17152 if (add_prefix)
17153 {
17154 oa->write_character(get_ubjson_float_prefix(n));
17155 }
17156 write_number(n, use_bjdata);
17157 }
17158
17159 // UBJSON: write number (unsigned integer)
17160 template<typename NumberType, typename std::enable_if<
17161 std::is_unsigned<NumberType>::value, int>::type = 0>
17162 void write_number_with_ubjson_prefix(const NumberType n,
17163 const bool add_prefix,
17164 const bool use_bjdata)
17165 {
17166 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17167 {
17168 if (add_prefix)
17169 {
17170 oa->write_character(to_char_type('i')); // int8
17171 }
17172 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17173 }
17174 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
17175 {
17176 if (add_prefix)
17177 {
17178 oa->write_character(to_char_type('U')); // uint8
17179 }
17180 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17181 }
17182 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17183 {
17184 if (add_prefix)
17185 {
17186 oa->write_character(to_char_type('I')); // int16
17187 }
17188 write_number(static_cast<std::int16_t>(n), use_bjdata);
17189 }
17190 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
17191 {
17192 if (add_prefix)
17193 {
17194 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17195 }
17196 write_number(static_cast<std::uint16_t>(n), use_bjdata);
17197 }
17198 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17199 {
17200 if (add_prefix)
17201 {
17202 oa->write_character(to_char_type('l')); // int32
17203 }
17204 write_number(static_cast<std::int32_t>(n), use_bjdata);
17205 }
17206 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
17207 {
17208 if (add_prefix)
17209 {
17210 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17211 }
17212 write_number(static_cast<std::uint32_t>(n), use_bjdata);
17213 }
17214 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17215 {
17216 if (add_prefix)
17217 {
17218 oa->write_character(to_char_type('L')); // int64
17219 }
17220 write_number(static_cast<std::int64_t>(n), use_bjdata);
17221 }
17222 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
17223 {
17224 if (add_prefix)
17225 {
17226 oa->write_character(to_char_type('M')); // uint64 - bjdata only
17227 }
17228 write_number(static_cast<std::uint64_t>(n), use_bjdata);
17229 }
17230 else
17231 {
17232 if (add_prefix)
17233 {
17234 oa->write_character(to_char_type('H')); // high-precision number
17235 }
17236
17237 const auto number = BasicJsonType(n).dump();
17238 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17239 for (std::size_t i = 0; i < number.size(); ++i)
17240 {
17241 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17242 }
17243 }
17244 }
17245
17246 // UBJSON: write number (signed integer)
17247 template < typename NumberType, typename std::enable_if <
17248 std::is_signed<NumberType>::value&&
17249 !std::is_floating_point<NumberType>::value, int >::type = 0 >
17250 void write_number_with_ubjson_prefix(const NumberType n,
17251 const bool add_prefix,
17252 const bool use_bjdata)
17253 {
17254 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
17255 {
17256 if (add_prefix)
17257 {
17258 oa->write_character(to_char_type('i')); // int8
17259 }
17260 write_number(static_cast<std::int8_t>(n), use_bjdata);
17261 }
17262 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
17263 {
17264 if (add_prefix)
17265 {
17266 oa->write_character(to_char_type('U')); // uint8
17267 }
17268 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17269 }
17270 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
17271 {
17272 if (add_prefix)
17273 {
17274 oa->write_character(to_char_type('I')); // int16
17275 }
17276 write_number(static_cast<std::int16_t>(n), use_bjdata);
17277 }
17278 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
17279 {
17280 if (add_prefix)
17281 {
17282 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17283 }
17284 write_number(static_cast<uint16_t>(n), use_bjdata);
17285 }
17286 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
17287 {
17288 if (add_prefix)
17289 {
17290 oa->write_character(to_char_type('l')); // int32
17291 }
17292 write_number(static_cast<std::int32_t>(n), use_bjdata);
17293 }
17294 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
17295 {
17296 if (add_prefix)
17297 {
17298 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17299 }
17300 write_number(static_cast<uint32_t>(n), use_bjdata);
17301 }
17302 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
17303 {
17304 if (add_prefix)
17305 {
17306 oa->write_character(to_char_type('L')); // int64
17307 }
17308 write_number(static_cast<std::int64_t>(n), use_bjdata);
17309 }
17310 // LCOV_EXCL_START
17311 else
17312 {
17313 if (add_prefix)
17314 {
17315 oa->write_character(to_char_type('H')); // high-precision number
17316 }
17317
17318 const auto number = BasicJsonType(n).dump();
17319 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17320 for (std::size_t i = 0; i < number.size(); ++i)
17321 {
17322 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17323 }
17324 }
17325 // LCOV_EXCL_STOP
17326 }
17327
17331 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
17332 {
17333 switch (j.type())
17334 {
17335 case value_t::null:
17336 return 'Z';
17337
17338 case value_t::boolean:
17339 return j.m_data.m_value.boolean ? 'T' : 'F';
17340
17341 case value_t::number_integer:
17342 {
17343 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
17344 {
17345 return 'i';
17346 }
17347 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
17348 {
17349 return 'U';
17350 }
17351 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
17352 {
17353 return 'I';
17354 }
17355 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
17356 {
17357 return 'u';
17358 }
17359 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
17360 {
17361 return 'l';
17362 }
17363 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
17364 {
17365 return 'm';
17366 }
17367 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
17368 {
17369 return 'L';
17370 }
17371 // anything else is treated as a high-precision number
17372 return 'H'; // LCOV_EXCL_LINE
17373 }
17374
17375 case value_t::number_unsigned:
17376 {
17377 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17378 {
17379 return 'i';
17380 }
17381 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
17382 {
17383 return 'U';
17384 }
17385 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17386 {
17387 return 'I';
17388 }
17389 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
17390 {
17391 return 'u';
17392 }
17393 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17394 {
17395 return 'l';
17396 }
17397 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
17398 {
17399 return 'm';
17400 }
17401 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17402 {
17403 return 'L';
17404 }
17405 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
17406 {
17407 return 'M';
17408 }
17409 // anything else is treated as a high-precision number
17410 return 'H'; // LCOV_EXCL_LINE
17411 }
17412
17413 case value_t::number_float:
17414 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
17415
17416 case value_t::string:
17417 return 'S';
17418
17419 case value_t::array: // fallthrough
17420 case value_t::binary:
17421 return '[';
17422
17423 case value_t::object:
17424 return '{';
17425
17426 case value_t::discarded:
17427 default: // discarded values
17428 return 'N';
17429 }
17430 }
17431
17432 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
17433 {
17434 return 'd'; // float 32
17435 }
17436
17437 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
17438 {
17439 return 'D'; // float 64
17440 }
17441
17445 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
17446 {
17447 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
17448 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
17449 {"char", 'C'}, {"byte", 'B'}
17450 };
17451
17452 string_t key = "_ArrayType_";
17453 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
17454 if (it == bjdtype.end())
17455 {
17456 return true;
17457 }
17458 CharType dtype = it->second;
17459
17460 key = "_ArraySize_";
17461 std::size_t len = (value.at(key).empty() ? 0 : 1);
17462 for (const auto& el : value.at(key))
17463 {
17464 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
17465 }
17466
17467 key = "_ArrayData_";
17468 if (value.at(key).size() != len)
17469 {
17470 return true;
17471 }
17472
17473 oa->write_character('[');
17474 oa->write_character('$');
17475 oa->write_character(dtype);
17476 oa->write_character('#');
17477
17478 key = "_ArraySize_";
17479 write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
17480
17481 key = "_ArrayData_";
17482 if (dtype == 'U' || dtype == 'C' || dtype == 'B')
17483 {
17484 for (const auto& el : value.at(key))
17485 {
17486 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
17487 }
17488 }
17489 else if (dtype == 'i')
17490 {
17491 for (const auto& el : value.at(key))
17492 {
17493 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
17494 }
17495 }
17496 else if (dtype == 'u')
17497 {
17498 for (const auto& el : value.at(key))
17499 {
17500 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
17501 }
17502 }
17503 else if (dtype == 'I')
17504 {
17505 for (const auto& el : value.at(key))
17506 {
17507 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
17508 }
17509 }
17510 else if (dtype == 'm')
17511 {
17512 for (const auto& el : value.at(key))
17513 {
17514 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
17515 }
17516 }
17517 else if (dtype == 'l')
17518 {
17519 for (const auto& el : value.at(key))
17520 {
17521 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
17522 }
17523 }
17524 else if (dtype == 'M')
17525 {
17526 for (const auto& el : value.at(key))
17527 {
17528 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
17529 }
17530 }
17531 else if (dtype == 'L')
17532 {
17533 for (const auto& el : value.at(key))
17534 {
17535 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
17536 }
17537 }
17538 else if (dtype == 'd')
17539 {
17540 for (const auto& el : value.at(key))
17541 {
17542 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
17543 }
17544 }
17545 else if (dtype == 'D')
17546 {
17547 for (const auto& el : value.at(key))
17548 {
17549 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
17550 }
17551 }
17552 return false;
17553 }
17554
17556 // Utility functions //
17558
17559 /*
17560 @brief write a number to output input
17561 @param[in] n number of type @a NumberType
17562 @param[in] OutputIsLittleEndian Set to true if output data is
17563 required to be little endian
17564 @tparam NumberType the type of the number
17565
17566 @note This function needs to respect the system's endianness, because bytes
17567 in CBOR, MessagePack, and UBJSON are stored in network order (big
17568 endian) and therefore need reordering on little endian systems.
17569 On the other hand, BSON and BJData use little endian and should reorder
17570 on big endian systems.
17571 */
17572 template<typename NumberType>
17573 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
17574 {
17575 // step 1: write the number to an array of length NumberType
17576 std::array<CharType, sizeof(NumberType)> vec{};
17577 std::memcpy(vec.data(), &n, sizeof(NumberType));
17578
17579 // step 2: write the array to output (with possible reordering)
17580 if (is_little_endian != OutputIsLittleEndian)
17581 {
17582 // reverse byte order prior to conversion if necessary
17583 std::reverse(vec.begin(), vec.end());
17584 }
17585
17586 oa->write_characters(vec.data(), sizeof(NumberType));
17587 }
17588
17589 void write_compact_float(const number_float_t n, detail::input_format_t format)
17590 {
17591#ifdef __GNUC__
17592#pragma GCC diagnostic push
17593#pragma GCC diagnostic ignored "-Wfloat-equal"
17594#endif
17595 if (!std::isfinite(n) || ((static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17596 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17597 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))))
17598 {
17599 oa->write_character(format == detail::input_format_t::cbor
17600 ? get_cbor_float_prefix(static_cast<float>(n))
17601 : get_msgpack_float_prefix(static_cast<float>(n)));
17602 write_number(static_cast<float>(n));
17603 }
17604 else
17605 {
17606 oa->write_character(format == detail::input_format_t::cbor
17607 ? get_cbor_float_prefix(n)
17608 : get_msgpack_float_prefix(n));
17609 write_number(n);
17610 }
17611#ifdef __GNUC__
17612#pragma GCC diagnostic pop
17613#endif
17614 }
17615
17616 public:
17617 // The following to_char_type functions are implement the conversion
17618 // between uint8_t and CharType. In case CharType is not unsigned,
17619 // such a conversion is required to allow values greater than 128.
17620 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17621 template < typename C = CharType,
17622 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17623 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17624 {
17625 return *reinterpret_cast<char*>(&x);
17626 }
17627
17628 template < typename C = CharType,
17629 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17630 static CharType to_char_type(std::uint8_t x) noexcept
17631 {
17632 // The std::is_trivial trait is deprecated in C++26. The replacement is to use
17633 // std::is_trivially_copyable and std::is_trivially_default_constructible.
17634 // However, some older library implementations support std::is_trivial
17635 // but not all the std::is_trivially_* traits.
17636 // Since detecting full support across all libraries is difficult,
17637 // we use std::is_trivial unless we are using a standard where it has been deprecated.
17638 // For more details, see: https://github.com/nlohmann/json/pull/4775#issuecomment-2884361627
17639#ifdef JSON_HAS_CPP_26
17640 static_assert(std::is_trivially_copyable<CharType>::value, "CharType must be trivially copyable");
17641 static_assert(std::is_trivially_default_constructible<CharType>::value, "CharType must be trivially default constructible");
17642#else
17643 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17644#endif
17645
17646 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17647 CharType result;
17648 std::memcpy(&result, &x, sizeof(x));
17649 return result;
17650 }
17651
17652 template<typename C = CharType,
17654 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17655 {
17656 return x;
17657 }
17658
17659 template < typename InputCharType, typename C = CharType,
17660 enable_if_t <
17661 std::is_signed<C>::value &&
17662 std::is_signed<char>::value &&
17663 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17664 > * = nullptr >
17665 static constexpr CharType to_char_type(InputCharType x) noexcept
17666 {
17667 return x;
17668 }
17669
17670 private:
17672 const bool is_little_endian = little_endianness();
17673
17675 output_adapter_t<CharType> oa = nullptr;
17676};
17677
17678} // namespace detail
17680
17681// #include <nlohmann/detail/output/output_adapters.hpp>
17682
17683// #include <nlohmann/detail/output/serializer.hpp>
17684// __ _____ _____ _____
17685// __| | __| | | | JSON for Modern C++
17686// | | |__ | | | | | | version 3.12.0
17687// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17688//
17689// SPDX-FileCopyrightText: 2008 - 2009 Bj철rn Hoehrmann <bjoern@hoehrmann.de>
17690// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17691// SPDX-License-Identifier: MIT
17692
17693
17694
17695#include <algorithm> // reverse, remove, fill, find, none_of
17696#include <array> // array
17697#include <clocale> // localeconv, lconv
17698#include <cmath> // labs, isfinite, isnan, signbit
17699#include <cstddef> // size_t, ptrdiff_t
17700#include <cstdint> // uint8_t
17701#include <cstdio> // snprintf
17702#include <limits> // numeric_limits
17703#include <string> // string, char_traits
17704#include <iomanip> // setfill, setw
17705#include <type_traits> // is_same
17706#include <utility> // move
17707
17708// #include <nlohmann/detail/conversions/to_chars.hpp>
17709// __ _____ _____ _____
17710// __| | __| | | | JSON for Modern C++
17711// | | |__ | | | | | | version 3.12.0
17712// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17713//
17714// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17715// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17716// SPDX-License-Identifier: MIT
17717
17718
17719
17720#include <array> // array
17721#include <cmath> // signbit, isfinite
17722#include <cstdint> // intN_t, uintN_t
17723#include <cstring> // memcpy, memmove
17724#include <limits> // numeric_limits
17725#include <type_traits> // conditional
17726
17727// #include <nlohmann/detail/macro_scope.hpp>
17728
17729
17731namespace detail
17732{
17733
17753namespace dtoa_impl
17754{
17755
17756template<typename Target, typename Source>
17757Target reinterpret_bits(const Source source)
17758{
17759 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17760
17761 Target target;
17762 std::memcpy(&target, &source, sizeof(Source));
17763 return target;
17764}
17765
17766struct diyfp // f * 2^e
17767{
17768 static constexpr int kPrecision = 64; // = q
17769
17770 std::uint64_t f = 0;
17771 int e = 0;
17772
17773 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17774
17779 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17780 {
17781 JSON_ASSERT(x.e == y.e);
17782 JSON_ASSERT(x.f >= y.f);
17783
17784 return {x.f - y.f, x.e};
17785 }
17786
17791 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17792 {
17793 static_assert(kPrecision == 64, "internal error");
17794
17795 // Computes:
17796 // f = round((x.f * y.f) / 2^q)
17797 // e = x.e + y.e + q
17798
17799 // Emulate the 64-bit * 64-bit multiplication:
17800 //
17801 // p = u * v
17802 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17803 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17804 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17805 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17806 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17807 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17808 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17809 //
17810 // (Since Q might be larger than 2^32 - 1)
17811 //
17812 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17813 //
17814 // (Q_hi + H does not overflow a 64-bit int)
17815 //
17816 // = p_lo + 2^64 p_hi
17817
17818 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17819 const std::uint64_t u_hi = x.f >> 32u;
17820 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17821 const std::uint64_t v_hi = y.f >> 32u;
17822
17823 const std::uint64_t p0 = u_lo * v_lo;
17824 const std::uint64_t p1 = u_lo * v_hi;
17825 const std::uint64_t p2 = u_hi * v_lo;
17826 const std::uint64_t p3 = u_hi * v_hi;
17827
17828 const std::uint64_t p0_hi = p0 >> 32u;
17829 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17830 const std::uint64_t p1_hi = p1 >> 32u;
17831 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17832 const std::uint64_t p2_hi = p2 >> 32u;
17833
17834 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17835
17836 // The full product might now be computed as
17837 //
17838 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17839 // p_lo = p0_lo + (Q << 32)
17840 //
17841 // But in this particular case here, the full p_lo is not required.
17842 // Effectively, we only need to add the highest bit in p_lo to p_hi (and
17843 // Q_hi + 1 does not overflow).
17844
17845 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17846
17847 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17848
17849 return {h, x.e + y.e + 64};
17850 }
17851
17856 static diyfp normalize(diyfp x) noexcept
17857 {
17858 JSON_ASSERT(x.f != 0);
17859
17860 while ((x.f >> 63u) == 0)
17861 {
17862 x.f <<= 1u;
17863 x.e--;
17864 }
17865
17866 return x;
17867 }
17868
17873 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17874 {
17875 const int delta = x.e - target_exponent;
17876
17877 JSON_ASSERT(delta >= 0);
17878 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17879
17880 return {x.f << delta, target_exponent};
17881 }
17882};
17883
17890
17897template<typename FloatType>
17899{
17900 JSON_ASSERT(std::isfinite(value));
17901 JSON_ASSERT(value > 0);
17902
17903 // Convert the IEEE representation into a diyfp.
17904 //
17905 // If v is denormal:
17906 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17907 // If v is normalized:
17908 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17909
17910 static_assert(std::numeric_limits<FloatType>::is_iec559,
17911 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17912
17913 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17914 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17915 constexpr int kMinExp = 1 - kBias;
17916 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17917
17918 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17919
17920 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17921 const std::uint64_t E = bits >> (kPrecision - 1);
17922 const std::uint64_t F = bits & (kHiddenBit - 1);
17923
17924 const bool is_denormal = E == 0;
17925 const diyfp v = is_denormal
17926 ? diyfp(F, kMinExp)
17927 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17928
17929 // Compute the boundaries m- and m+ of the floating-point value
17930 // v = f * 2^e.
17931 //
17932 // Determine v- and v+, the floating-point predecessor and successor of v,
17933 // respectively.
17934 //
17935 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17936 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17937 //
17938 // v+ = v + 2^e
17939 //
17940 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17941 // between m- and m+ round to v, regardless of how the input rounding
17942 // algorithm breaks ties.
17943 //
17944 // ---+-------------+-------------+-------------+-------------+--- (A)
17945 // v- m- v m+ v+
17946 //
17947 // -----------------+------+------+-------------+-------------+--- (B)
17948 // v- m- v m+ v+
17949
17950 const bool lower_boundary_is_closer = F == 0 && E > 1;
17951 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17952 const diyfp m_minus = lower_boundary_is_closer
17953 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
17954 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17955
17956 // Determine the normalized w+ = m+.
17957 const diyfp w_plus = diyfp::normalize(m_plus);
17958
17959 // Determine w- = m- such that e_(w-) = e_(w+).
17960 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17961
17962 return {diyfp::normalize(v), w_minus, w_plus};
17963}
17964
17965// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17966// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17967// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17968//
17969// alpha <= e = e_c + e_w + q <= gamma
17970//
17971// or
17972//
17973// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17974// <= f_c * f_w * 2^gamma
17975//
17976// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17977//
17978// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17979//
17980// or
17981//
17982// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17983//
17984// The choice of (alpha,gamma) determines the size of the table and the form of
17985// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17986// in practice:
17987//
17988// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17989// processed independently: An integral part p1, and a fractional part p2:
17990//
17991// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17992// = (f div 2^-e) + (f mod 2^-e) * 2^e
17993// = p1 + p2 * 2^e
17994//
17995// The conversion of p1 into decimal form requires a series of divisions and
17996// modulos by (a power of) 10. These operations are faster for 32-bit than for
17997// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17998// achieved by choosing
17999//
18000// -e >= 32 or e <= -32 := gamma
18001//
18002// In order to convert the fractional part
18003//
18004// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
18005//
18006// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
18007// d[-i] are extracted in order:
18008//
18009// (10 * p2) div 2^-e = d[-1]
18010// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
18011//
18012// The multiplication by 10 must not overflow. It is sufficient to choose
18013//
18014// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
18015//
18016// Since p2 = f mod 2^-e < 2^-e,
18017//
18018// -e <= 60 or e >= -60 := alpha
18019
18020constexpr int kAlpha = -60;
18021constexpr int kGamma = -32;
18022
18023struct cached_power // c = f * 2^e ~= 10^k
18024{
18025 std::uint64_t f;
18026 int e;
18027 int k;
18028};
18029
18038{
18039 // Now
18040 //
18041 // alpha <= e_c + e + q <= gamma (1)
18042 // ==> f_c * 2^alpha <= c * 2^e * 2^q
18043 //
18044 // and since the c's are normalized, 2^(q-1) <= f_c,
18045 //
18046 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
18047 // ==> 2^(alpha - e - 1) <= c
18048 //
18049 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
18050 //
18051 // k = ceil( log_10( 2^(alpha - e - 1) ) )
18052 // = ceil( (alpha - e - 1) * log_10(2) )
18053 //
18054 // From the paper:
18055 // "In theory the result of the procedure could be wrong since c is rounded,
18056 // and the computation itself is approximated [...]. In practice, however,
18057 // this simple function is sufficient."
18058 //
18059 // For IEEE double precision floating-point numbers converted into
18060 // normalized diyfp's w = f * 2^e, with q = 64,
18061 //
18062 // e >= -1022 (min IEEE exponent)
18063 // -52 (p - 1)
18064 // -52 (p - 1, possibly normalize denormal IEEE numbers)
18065 // -11 (normalize the diyfp)
18066 // = -1137
18067 //
18068 // and
18069 //
18070 // e <= +1023 (max IEEE exponent)
18071 // -52 (p - 1)
18072 // -11 (normalize the diyfp)
18073 // = 960
18074 //
18075 // This binary exponent range [-1137,960] results in a decimal exponent
18076 // range [-307,324]. One does not need to store a cached power for each
18077 // k in this range. For each such k it suffices to find a cached power
18078 // such that the exponent of the product lies in [alpha,gamma].
18079 // This implies that the difference of the decimal exponents of adjacent
18080 // table entries must be less than or equal to
18081 //
18082 // floor( (gamma - alpha) * log_10(2) ) = 8.
18083 //
18084 // (A smaller distance gamma-alpha would require a larger table.)
18085
18086 // NB:
18087 // Actually, this function returns c, such that -60 <= e_c + e + 64 <= -34.
18088
18089 constexpr int kCachedPowersMinDecExp = -300;
18090 constexpr int kCachedPowersDecStep = 8;
18091
18092 static constexpr std::array<cached_power, 79> kCachedPowers =
18093 {
18094 {
18095 { 0xAB70FE17C79AC6CA, -1060, -300 },
18096 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
18097 { 0xBE5691EF416BD60C, -1007, -284 },
18098 { 0x8DD01FAD907FFC3C, -980, -276 },
18099 { 0xD3515C2831559A83, -954, -268 },
18100 { 0x9D71AC8FADA6C9B5, -927, -260 },
18101 { 0xEA9C227723EE8BCB, -901, -252 },
18102 { 0xAECC49914078536D, -874, -244 },
18103 { 0x823C12795DB6CE57, -847, -236 },
18104 { 0xC21094364DFB5637, -821, -228 },
18105 { 0x9096EA6F3848984F, -794, -220 },
18106 { 0xD77485CB25823AC7, -768, -212 },
18107 { 0xA086CFCD97BF97F4, -741, -204 },
18108 { 0xEF340A98172AACE5, -715, -196 },
18109 { 0xB23867FB2A35B28E, -688, -188 },
18110 { 0x84C8D4DFD2C63F3B, -661, -180 },
18111 { 0xC5DD44271AD3CDBA, -635, -172 },
18112 { 0x936B9FCEBB25C996, -608, -164 },
18113 { 0xDBAC6C247D62A584, -582, -156 },
18114 { 0xA3AB66580D5FDAF6, -555, -148 },
18115 { 0xF3E2F893DEC3F126, -529, -140 },
18116 { 0xB5B5ADA8AAFF80B8, -502, -132 },
18117 { 0x87625F056C7C4A8B, -475, -124 },
18118 { 0xC9BCFF6034C13053, -449, -116 },
18119 { 0x964E858C91BA2655, -422, -108 },
18120 { 0xDFF9772470297EBD, -396, -100 },
18121 { 0xA6DFBD9FB8E5B88F, -369, -92 },
18122 { 0xF8A95FCF88747D94, -343, -84 },
18123 { 0xB94470938FA89BCF, -316, -76 },
18124 { 0x8A08F0F8BF0F156B, -289, -68 },
18125 { 0xCDB02555653131B6, -263, -60 },
18126 { 0x993FE2C6D07B7FAC, -236, -52 },
18127 { 0xE45C10C42A2B3B06, -210, -44 },
18128 { 0xAA242499697392D3, -183, -36 },
18129 { 0xFD87B5F28300CA0E, -157, -28 },
18130 { 0xBCE5086492111AEB, -130, -20 },
18131 { 0x8CBCCC096F5088CC, -103, -12 },
18132 { 0xD1B71758E219652C, -77, -4 },
18133 { 0x9C40000000000000, -50, 4 },
18134 { 0xE8D4A51000000000, -24, 12 },
18135 { 0xAD78EBC5AC620000, 3, 20 },
18136 { 0x813F3978F8940984, 30, 28 },
18137 { 0xC097CE7BC90715B3, 56, 36 },
18138 { 0x8F7E32CE7BEA5C70, 83, 44 },
18139 { 0xD5D238A4ABE98068, 109, 52 },
18140 { 0x9F4F2726179A2245, 136, 60 },
18141 { 0xED63A231D4C4FB27, 162, 68 },
18142 { 0xB0DE65388CC8ADA8, 189, 76 },
18143 { 0x83C7088E1AAB65DB, 216, 84 },
18144 { 0xC45D1DF942711D9A, 242, 92 },
18145 { 0x924D692CA61BE758, 269, 100 },
18146 { 0xDA01EE641A708DEA, 295, 108 },
18147 { 0xA26DA3999AEF774A, 322, 116 },
18148 { 0xF209787BB47D6B85, 348, 124 },
18149 { 0xB454E4A179DD1877, 375, 132 },
18150 { 0x865B86925B9BC5C2, 402, 140 },
18151 { 0xC83553C5C8965D3D, 428, 148 },
18152 { 0x952AB45CFA97A0B3, 455, 156 },
18153 { 0xDE469FBD99A05FE3, 481, 164 },
18154 { 0xA59BC234DB398C25, 508, 172 },
18155 { 0xF6C69A72A3989F5C, 534, 180 },
18156 { 0xB7DCBF5354E9BECE, 561, 188 },
18157 { 0x88FCF317F22241E2, 588, 196 },
18158 { 0xCC20CE9BD35C78A5, 614, 204 },
18159 { 0x98165AF37B2153DF, 641, 212 },
18160 { 0xE2A0B5DC971F303A, 667, 220 },
18161 { 0xA8D9D1535CE3B396, 694, 228 },
18162 { 0xFB9B7CD9A4A7443C, 720, 236 },
18163 { 0xBB764C4CA7A44410, 747, 244 },
18164 { 0x8BAB8EEFB6409C1A, 774, 252 },
18165 { 0xD01FEF10A657842C, 800, 260 },
18166 { 0x9B10A4E5E9913129, 827, 268 },
18167 { 0xE7109BFBA19C0C9D, 853, 276 },
18168 { 0xAC2820D9623BF429, 880, 284 },
18169 { 0x80444B5E7AA7CF85, 907, 292 },
18170 { 0xBF21E44003ACDD2D, 933, 300 },
18171 { 0x8E679C2F5E44FF8F, 960, 308 },
18172 { 0xD433179D9C8CB841, 986, 316 },
18173 { 0x9E19DB92B4E31BA9, 1013, 324 },
18174 }
18175 };
18176
18177 // This computation gives exactly the same results for k as
18178 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
18179 // for |e| <= 1500, but doesn't require floating-point operations.
18180 // NB: log_10(2) ~= 78913 / 2^18
18181 JSON_ASSERT(e >= -1500);
18182 JSON_ASSERT(e <= 1500);
18183 const int f = kAlpha - e - 1;
18184 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
18185
18186 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
18187 JSON_ASSERT(index >= 0);
18188 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
18189
18190 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
18191 JSON_ASSERT(kAlpha <= cached.e + e + 64);
18192 JSON_ASSERT(kGamma >= cached.e + e + 64);
18193
18194 return cached;
18195}
18196
18201inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
18202{
18203 // LCOV_EXCL_START
18204 if (n >= 1000000000)
18205 {
18206 pow10 = 1000000000;
18207 return 10;
18208 }
18209 // LCOV_EXCL_STOP
18210 if (n >= 100000000)
18211 {
18212 pow10 = 100000000;
18213 return 9;
18214 }
18215 if (n >= 10000000)
18216 {
18217 pow10 = 10000000;
18218 return 8;
18219 }
18220 if (n >= 1000000)
18221 {
18222 pow10 = 1000000;
18223 return 7;
18224 }
18225 if (n >= 100000)
18226 {
18227 pow10 = 100000;
18228 return 6;
18229 }
18230 if (n >= 10000)
18231 {
18232 pow10 = 10000;
18233 return 5;
18234 }
18235 if (n >= 1000)
18236 {
18237 pow10 = 1000;
18238 return 4;
18239 }
18240 if (n >= 100)
18241 {
18242 pow10 = 100;
18243 return 3;
18244 }
18245 if (n >= 10)
18246 {
18247 pow10 = 10;
18248 return 2;
18249 }
18250
18251 pow10 = 1;
18252 return 1;
18253}
18254
18255inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
18256 std::uint64_t rest, std::uint64_t ten_k)
18257{
18258 JSON_ASSERT(len >= 1);
18259 JSON_ASSERT(dist <= delta);
18260 JSON_ASSERT(rest <= delta);
18261 JSON_ASSERT(ten_k > 0);
18262
18263 // <--------------------------- delta ---->
18264 // <---- dist --------->
18265 // --------------[------------------+-------------------]--------------
18266 // M- w M+
18267 //
18268 // ten_k
18269 // <------>
18270 // <---- rest ---->
18271 // --------------[------------------+----+--------------]--------------
18272 // w V
18273 // = buf * 10^k
18274 //
18275 // ten_k represents a unit-in-the-last-place in the decimal representation
18276 // stored in buf.
18277 // Decrement buf by ten_k while this takes buf closer to w.
18278
18279 // The tests are written in this order to avoid overflow in unsigned
18280 // integer arithmetic.
18281
18282 while (rest < dist
18283 && delta - rest >= ten_k
18284 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
18285 {
18286 JSON_ASSERT(buf[len - 1] != '0');
18287 buf[len - 1]--;
18288 rest += ten_k;
18289 }
18290}
18291
18296inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
18297 diyfp M_minus, diyfp w, diyfp M_plus)
18298{
18299 static_assert(kAlpha >= -60, "internal error");
18300 static_assert(kGamma <= -32, "internal error");
18301
18302 // Generates the digits (and the exponent) of a decimal floating-point
18303 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
18304 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
18305 //
18306 // <--------------------------- delta ---->
18307 // <---- dist --------->
18308 // --------------[------------------+-------------------]--------------
18309 // M- w M+
18310 //
18311 // Grisu2 generates the digits of M+ from left to right and stops as soon as
18312 // V is in [M-,M+].
18313
18314 JSON_ASSERT(M_plus.e >= kAlpha);
18315 JSON_ASSERT(M_plus.e <= kGamma);
18316
18317 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
18318 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
18319
18320 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
18321 //
18322 // M+ = f * 2^e
18323 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
18324 // = ((p1 ) * 2^-e + (p2 )) * 2^e
18325 // = p1 + p2 * 2^e
18326
18327 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
18328
18329 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
18330 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
18331
18332 // 1)
18333 //
18334 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
18335
18336 JSON_ASSERT(p1 > 0);
18337
18338 std::uint32_t pow10{};
18339 const int k = find_largest_pow10(p1, pow10);
18340
18341 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
18342 //
18343 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
18344 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
18345 //
18346 // M+ = p1 + p2 * 2^e
18347 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
18348 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
18349 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
18350 //
18351 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
18352 //
18353 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
18354 //
18355 // but stop as soon as
18356 //
18357 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
18358
18359 int n = k;
18360 while (n > 0)
18361 {
18362 // Invariants:
18363 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
18364 // pow10 = 10^(n-1) <= p1 < 10^n
18365 //
18366 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
18367 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
18368 //
18369 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
18370 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
18371 //
18372 JSON_ASSERT(d <= 9);
18373 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18374 //
18375 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
18376 //
18377 p1 = r;
18378 n--;
18379 //
18380 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
18381 // pow10 = 10^n
18382 //
18383
18384 // Now check if enough digits have been generated.
18385 // Compute
18386 //
18387 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
18388 //
18389 // Note:
18390 // Since rest and delta share the same exponent e, it suffices to
18391 // compare the significands.
18392 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
18393 if (rest <= delta)
18394 {
18395 // V = buffer * 10^n, with M- <= V <= M+.
18396
18397 decimal_exponent += n;
18398
18399 // We may now just stop. But instead, it looks as if the buffer
18400 // could be decremented to bring V closer to w.
18401 //
18402 // pow10 = 10^n is now 1 ulp in the decimal representation V.
18403 // The rounding procedure works with diyfp's with an implicit
18404 // exponent of e.
18405 //
18406 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
18407 //
18408 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
18409 grisu2_round(buffer, length, dist, delta, rest, ten_n);
18410
18411 return;
18412 }
18413
18414 pow10 /= 10;
18415 //
18416 // pow10 = 10^(n-1) <= p1 < 10^n
18417 // Invariants restored.
18418 }
18419
18420 // 2)
18421 //
18422 // The digits of the integral part have been generated:
18423 //
18424 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
18425 // = buffer + p2 * 2^e
18426 //
18427 // Now generate the digits of the fractional part p2 * 2^e.
18428 //
18429 // Note:
18430 // No decimal point is generated: the exponent is adjusted instead.
18431 //
18432 // p2 actually represents the fraction
18433 //
18434 // p2 * 2^e
18435 // = p2 / 2^-e
18436 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
18437 //
18438 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
18439 //
18440 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
18441 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
18442 //
18443 // using
18444 //
18445 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
18446 // = ( d) * 2^-e + ( r)
18447 //
18448 // or
18449 // 10^m * p2 * 2^e = d + r * 2^e
18450 //
18451 // i.e.
18452 //
18453 // M+ = buffer + p2 * 2^e
18454 // = buffer + 10^-m * (d + r * 2^e)
18455 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
18456 //
18457 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
18458
18459 JSON_ASSERT(p2 > delta);
18460
18461 int m = 0;
18462 for (;;)
18463 {
18464 // Invariant:
18465 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
18466 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
18467 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
18468 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
18469 //
18470 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
18471 p2 *= 10;
18472 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
18473 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
18474 //
18475 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
18476 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
18477 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
18478 //
18479 JSON_ASSERT(d <= 9);
18480 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18481 //
18482 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
18483 //
18484 p2 = r;
18485 m++;
18486 //
18487 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
18488 // Invariant restored.
18489
18490 // Check if enough digits have been generated.
18491 //
18492 // 10^-m * p2 * 2^e <= delta * 2^e
18493 // p2 * 2^e <= 10^m * delta * 2^e
18494 // p2 <= 10^m * delta
18495 delta *= 10;
18496 dist *= 10;
18497 if (p2 <= delta)
18498 {
18499 break;
18500 }
18501 }
18502
18503 // V = buffer * 10^-m, with M- <= V <= M+.
18504
18505 decimal_exponent -= m;
18506
18507 // 1 ulp in the decimal representation is now 10^-m.
18508 // Since delta and dist are now scaled by 10^m, we need to do the
18509 // same with ulp in order to keep the units in sync.
18510 //
18511 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
18512 //
18513 const std::uint64_t ten_m = one.f;
18514 grisu2_round(buffer, length, dist, delta, p2, ten_m);
18515
18516 // By construction this algorithm generates the shortest possible decimal
18517 // number (Loitsch, Theorem 6.2) which rounds back to w.
18518 // For an input number of precision p, at least
18519 //
18520 // N = 1 + ceil(p * log_10(2))
18521 //
18522 // decimal digits are sufficient to identify all binary floating-point
18523 // numbers (Matula, "In-and-Out conversions").
18524 // This implies that the algorithm does not produce more than N decimal
18525 // digits.
18526 //
18527 // N = 17 for p = 53 (IEEE double precision)
18528 // N = 9 for p = 24 (IEEE single precision)
18529}
18530
18537inline void grisu2(char* buf, int& len, int& decimal_exponent,
18538 diyfp m_minus, diyfp v, diyfp m_plus)
18539{
18540 JSON_ASSERT(m_plus.e == m_minus.e);
18541 JSON_ASSERT(m_plus.e == v.e);
18542
18543 // --------(-----------------------+-----------------------)-------- (A)
18544 // m- v m+
18545 //
18546 // --------------------(-----------+-----------------------)-------- (B)
18547 // m- v m+
18548 //
18549 // First scale v (and m- and m+) such that the exponent is in the range
18550 // [alpha, gamma].
18551
18552 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
18553
18554 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
18555
18556 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
18557 const diyfp w = diyfp::mul(v, c_minus_k);
18558 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
18559 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
18560
18561 // ----(---+---)---------------(---+---)---------------(---+---)----
18562 // w- w w+
18563 // = c*m- = c*v = c*m+
18564 //
18565 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
18566 // w+ are now off by a small amount.
18567 // In fact:
18568 //
18569 // w - v * 10^k < 1 ulp
18570 //
18571 // To account for this inaccuracy, add resp. subtract 1 ulp.
18572 //
18573 // --------+---[---------------(---+---)---------------]---+--------
18574 // w- M- w M+ w+
18575 //
18576 // Now any number in [M-, M+] (bounds included) will round to w when input,
18577 // regardless of how the input rounding algorithm breaks ties.
18578 //
18579 // And digit_gen generates the shortest possible such number in [M-, M+].
18580 // Note that this does not mean that Grisu2 always generates the shortest
18581 // possible number in the interval (m-, m+).
18582 const diyfp M_minus(w_minus.f + 1, w_minus.e);
18583 const diyfp M_plus (w_plus.f - 1, w_plus.e );
18584
18585 decimal_exponent = -cached.k; // = -(-k) = k
18586
18587 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
18588}
18589
18595template<typename FloatType>
18597void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
18598{
18599 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
18600 "internal error: not enough precision");
18601
18602 JSON_ASSERT(std::isfinite(value));
18603 JSON_ASSERT(value > 0);
18604
18605 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18606 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18607 // decimal representations are not exactly "short".
18608 //
18609 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18610 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18611 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18612 // does.
18613 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18614 // representation using the corresponding std::from_chars function recovers value exactly". That
18615 // indicates that single precision floating-point numbers should be recovered using
18616 // 'std::strtof'.
18617 //
18618 // NB: If the neighbors are computed for single-precision numbers, there is a single float
18619 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18620 // value is off by 1 ulp.
18621#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18622 const boundaries w = compute_boundaries(static_cast<double>(value));
18623#else
18625#endif
18626
18627 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18628}
18629
18637inline char* append_exponent(char* buf, int e)
18638{
18639 JSON_ASSERT(e > -1000);
18640 JSON_ASSERT(e < 1000);
18641
18642 if (e < 0)
18643 {
18644 e = -e;
18645 *buf++ = '-';
18646 }
18647 else
18648 {
18649 *buf++ = '+';
18650 }
18651
18652 auto k = static_cast<std::uint32_t>(e);
18653 if (k < 10)
18654 {
18655 // Always print at least two digits in the exponent.
18656 // This is for compatibility with printf("%g").
18657 *buf++ = '0';
18658 *buf++ = static_cast<char>('0' + k);
18659 }
18660 else if (k < 100)
18661 {
18662 *buf++ = static_cast<char>('0' + (k / 10));
18663 k %= 10;
18664 *buf++ = static_cast<char>('0' + k);
18665 }
18666 else
18667 {
18668 *buf++ = static_cast<char>('0' + (k / 100));
18669 k %= 100;
18670 *buf++ = static_cast<char>('0' + (k / 10));
18671 k %= 10;
18672 *buf++ = static_cast<char>('0' + k);
18673 }
18674
18675 return buf;
18676}
18677
18689inline char* format_buffer(char* buf, int len, int decimal_exponent,
18690 int min_exp, int max_exp)
18691{
18692 JSON_ASSERT(min_exp < 0);
18693 JSON_ASSERT(max_exp > 0);
18694
18695 const int k = len;
18696 const int n = len + decimal_exponent;
18697
18698 // v = buf * 10^(n-k)
18699 // k is the length of the buffer (number of decimal digits)
18700 // n is the position of the decimal point relative to the start of the buffer.
18701
18702 if (k <= n && n <= max_exp)
18703 {
18704 // digits[000]
18705 // len <= max_exp + 2
18706
18707 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18708 // Make it look like a floating-point number (#362, #378)
18709 buf[n + 0] = '.';
18710 buf[n + 1] = '0';
18711 return buf + (static_cast<size_t>(n) + 2);
18712 }
18713
18714 if (0 < n && n <= max_exp)
18715 {
18716 // dig.its
18717 // len <= max_digits10 + 1
18718
18719 JSON_ASSERT(k > n);
18720
18721 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18722 buf[n] = '.';
18723 return buf + (static_cast<size_t>(k) + 1U);
18724 }
18725
18726 if (min_exp < n && n <= 0)
18727 {
18728 // 0.[000]digits
18729 // len <= 2 + (-min_exp - 1) + max_digits10
18730
18731 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18732 buf[0] = '0';
18733 buf[1] = '.';
18734 std::memset(buf + 2, '0', static_cast<size_t>(-n));
18735 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18736 }
18737
18738 if (k == 1)
18739 {
18740 // dE+123
18741 // len <= 1 + 5
18742
18743 buf += 1;
18744 }
18745 else
18746 {
18747 // d.igitsE+123
18748 // len <= max_digits10 + 1 + 5
18749
18750 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18751 buf[1] = '.';
18752 buf += 1 + static_cast<size_t>(k);
18753 }
18754
18755 *buf++ = 'e';
18756 return append_exponent(buf, n - 1);
18757}
18758
18759} // namespace dtoa_impl
18760
18771template<typename FloatType>
18774char* to_chars(char* first, const char* last, FloatType value)
18775{
18776 static_cast<void>(last); // maybe unused - fix warning
18777 JSON_ASSERT(std::isfinite(value));
18778
18779 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18780 if (std::signbit(value))
18781 {
18782 value = -value;
18783 *first++ = '-';
18784 }
18785
18786#ifdef __GNUC__
18787#pragma GCC diagnostic push
18788#pragma GCC diagnostic ignored "-Wfloat-equal"
18789#endif
18790 if (value == 0) // +-0
18791 {
18792 *first++ = '0';
18793 // Make it look like a floating-point number (#362, #378)
18794 *first++ = '.';
18795 *first++ = '0';
18796 return first;
18797 }
18798#ifdef __GNUC__
18799#pragma GCC diagnostic pop
18800#endif
18801
18802 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18803
18804 // Compute v = buffer * 10^decimal_exponent.
18805 // The decimal digits are stored in the buffer, which needs to be interpreted
18806 // as an unsigned decimal integer.
18807 // len is the length of the buffer, i.e., the number of decimal digits.
18808 int len = 0;
18809 int decimal_exponent = 0;
18810 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18811
18812 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18813
18814 // Format the buffer like printf("%.*g", prec, value)
18815 constexpr int kMinExp = -4;
18816 // Use digits10 here to increase compatibility with version 2.
18817 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18818
18819 JSON_ASSERT(last - first >= kMaxExp + 2);
18820 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18821 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18822
18823 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18824}
18825
18826} // namespace detail
18828
18829// #include <nlohmann/detail/exceptions.hpp>
18830
18831// #include <nlohmann/detail/macro_scope.hpp>
18832
18833// #include <nlohmann/detail/meta/cpp_future.hpp>
18834
18835// #include <nlohmann/detail/output/binary_writer.hpp>
18836
18837// #include <nlohmann/detail/output/output_adapters.hpp>
18838
18839// #include <nlohmann/detail/string_concat.hpp>
18840
18841// #include <nlohmann/detail/value_t.hpp>
18842
18843
18845namespace detail
18846{
18847
18849// serialization //
18851
18854{
18858};
18859
18860template<typename BasicJsonType>
18862{
18863 using string_t = typename BasicJsonType::string_t;
18864 using number_float_t = typename BasicJsonType::number_float_t;
18865 using number_integer_t = typename BasicJsonType::number_integer_t;
18866 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18867 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18868 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18869 static constexpr std::uint8_t UTF8_REJECT = 1;
18870
18871 public:
18879 : o(std::move(s))
18880 , loc(std::localeconv())
18881 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18882 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18883 , indent_char(ichar)
18885 , error_handler(error_handler_)
18886 {}
18887
18888 // deleted because of pointer members
18889 serializer(const serializer&) = delete;
18893 ~serializer() = default;
18894
18917 void dump(const BasicJsonType& val,
18918 const bool pretty_print,
18919 const bool ensure_ascii,
18920 const unsigned int indent_step,
18921 const unsigned int current_indent = 0)
18922 {
18923 switch (val.m_data.m_type)
18924 {
18925 case value_t::object:
18926 {
18927 if (val.m_data.m_value.object->empty())
18928 {
18929 o->write_characters("{}", 2);
18930 return;
18931 }
18932
18933 if (pretty_print)
18934 {
18935 o->write_characters("{\n", 2);
18936
18937 // variable to hold indentation for recursive calls
18938 const auto new_indent = current_indent + indent_step;
18939 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18940 {
18941 indent_string.resize(indent_string.size() * 2, ' ');
18942 }
18943
18944 // first n-1 elements
18945 auto i = val.m_data.m_value.object->cbegin();
18946 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18947 {
18948 o->write_characters(indent_string.c_str(), new_indent);
18949 o->write_character('\"');
18950 dump_escaped(i->first, ensure_ascii);
18951 o->write_characters("\": ", 3);
18952 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18953 o->write_characters(",\n", 2);
18954 }
18955
18956 // last element
18957 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18958 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18959 o->write_characters(indent_string.c_str(), new_indent);
18960 o->write_character('\"');
18961 dump_escaped(i->first, ensure_ascii);
18962 o->write_characters("\": ", 3);
18963 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18964
18965 o->write_character('\n');
18966 o->write_characters(indent_string.c_str(), current_indent);
18967 o->write_character('}');
18968 }
18969 else
18970 {
18971 o->write_character('{');
18972
18973 // first n-1 elements
18974 auto i = val.m_data.m_value.object->cbegin();
18975 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18976 {
18977 o->write_character('\"');
18978 dump_escaped(i->first, ensure_ascii);
18979 o->write_characters("\":", 2);
18980 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18981 o->write_character(',');
18982 }
18983
18984 // last element
18985 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18986 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18987 o->write_character('\"');
18988 dump_escaped(i->first, ensure_ascii);
18989 o->write_characters("\":", 2);
18990 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18991
18992 o->write_character('}');
18993 }
18994
18995 return;
18996 }
18997
18998 case value_t::array:
18999 {
19000 if (val.m_data.m_value.array->empty())
19001 {
19002 o->write_characters("[]", 2);
19003 return;
19004 }
19005
19006 if (pretty_print)
19007 {
19008 o->write_characters("[\n", 2);
19009
19010 // variable to hold indentation for recursive calls
19011 const auto new_indent = current_indent + indent_step;
19012 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19013 {
19014 indent_string.resize(indent_string.size() * 2, ' ');
19015 }
19016
19017 // first n-1 elements
19018 for (auto i = val.m_data.m_value.array->cbegin();
19019 i != val.m_data.m_value.array->cend() - 1; ++i)
19020 {
19021 o->write_characters(indent_string.c_str(), new_indent);
19022 dump(*i, true, ensure_ascii, indent_step, new_indent);
19023 o->write_characters(",\n", 2);
19024 }
19025
19026 // last element
19027 JSON_ASSERT(!val.m_data.m_value.array->empty());
19028 o->write_characters(indent_string.c_str(), new_indent);
19029 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
19030
19031 o->write_character('\n');
19032 o->write_characters(indent_string.c_str(), current_indent);
19033 o->write_character(']');
19034 }
19035 else
19036 {
19037 o->write_character('[');
19038
19039 // first n-1 elements
19040 for (auto i = val.m_data.m_value.array->cbegin();
19041 i != val.m_data.m_value.array->cend() - 1; ++i)
19042 {
19043 dump(*i, false, ensure_ascii, indent_step, current_indent);
19044 o->write_character(',');
19045 }
19046
19047 // last element
19048 JSON_ASSERT(!val.m_data.m_value.array->empty());
19049 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
19050
19051 o->write_character(']');
19052 }
19053
19054 return;
19055 }
19056
19057 case value_t::string:
19058 {
19059 o->write_character('\"');
19060 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
19061 o->write_character('\"');
19062 return;
19063 }
19064
19065 case value_t::binary:
19066 {
19067 if (pretty_print)
19068 {
19069 o->write_characters("{\n", 2);
19070
19071 // variable to hold indentation for recursive calls
19072 const auto new_indent = current_indent + indent_step;
19073 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19074 {
19075 indent_string.resize(indent_string.size() * 2, ' ');
19076 }
19077
19078 o->write_characters(indent_string.c_str(), new_indent);
19079
19080 o->write_characters("\"bytes\": [", 10);
19081
19082 if (!val.m_data.m_value.binary->empty())
19083 {
19084 for (auto i = val.m_data.m_value.binary->cbegin();
19085 i != val.m_data.m_value.binary->cend() - 1; ++i)
19086 {
19087 dump_integer(*i);
19088 o->write_characters(", ", 2);
19089 }
19090 dump_integer(val.m_data.m_value.binary->back());
19091 }
19092
19093 o->write_characters("],\n", 3);
19094 o->write_characters(indent_string.c_str(), new_indent);
19095
19096 o->write_characters("\"subtype\": ", 11);
19097 if (val.m_data.m_value.binary->has_subtype())
19098 {
19099 dump_integer(val.m_data.m_value.binary->subtype());
19100 }
19101 else
19102 {
19103 o->write_characters("null", 4);
19104 }
19105 o->write_character('\n');
19106 o->write_characters(indent_string.c_str(), current_indent);
19107 o->write_character('}');
19108 }
19109 else
19110 {
19111 o->write_characters("{\"bytes\":[", 10);
19112
19113 if (!val.m_data.m_value.binary->empty())
19114 {
19115 for (auto i = val.m_data.m_value.binary->cbegin();
19116 i != val.m_data.m_value.binary->cend() - 1; ++i)
19117 {
19118 dump_integer(*i);
19119 o->write_character(',');
19120 }
19121 dump_integer(val.m_data.m_value.binary->back());
19122 }
19123
19124 o->write_characters("],\"subtype\":", 12);
19125 if (val.m_data.m_value.binary->has_subtype())
19126 {
19127 dump_integer(val.m_data.m_value.binary->subtype());
19128 o->write_character('}');
19129 }
19130 else
19131 {
19132 o->write_characters("null}", 5);
19133 }
19134 }
19135 return;
19136 }
19137
19138 case value_t::boolean:
19139 {
19140 if (val.m_data.m_value.boolean)
19141 {
19142 o->write_characters("true", 4);
19143 }
19144 else
19145 {
19146 o->write_characters("false", 5);
19147 }
19148 return;
19149 }
19150
19152 {
19153 dump_integer(val.m_data.m_value.number_integer);
19154 return;
19155 }
19156
19158 {
19159 dump_integer(val.m_data.m_value.number_unsigned);
19160 return;
19161 }
19162
19164 {
19165 dump_float(val.m_data.m_value.number_float);
19166 return;
19167 }
19168
19169 case value_t::discarded:
19170 {
19171 o->write_characters("<discarded>", 11);
19172 return;
19173 }
19174
19175 case value_t::null:
19176 {
19177 o->write_characters("null", 4);
19178 return;
19179 }
19180
19181 default: // LCOV_EXCL_LINE
19182 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19183 }
19184 }
19185
19201 void dump_escaped(const string_t& s, const bool ensure_ascii)
19202 {
19203 std::uint32_t codepoint{};
19204 std::uint8_t state = UTF8_ACCEPT;
19205 std::size_t bytes = 0; // number of bytes written to string_buffer
19206
19207 // number of bytes written at the point of the last valid byte
19209 std::size_t undumped_chars = 0;
19210
19211 for (std::size_t i = 0; i < s.size(); ++i)
19212 {
19213 const auto byte = static_cast<std::uint8_t>(s[i]);
19214
19215 switch (decode(state, codepoint, byte))
19216 {
19217 case UTF8_ACCEPT: // decode found a new code point
19218 {
19219 switch (codepoint)
19220 {
19221 case 0x08: // backspace
19222 {
19223 string_buffer[bytes++] = '\\';
19224 string_buffer[bytes++] = 'b';
19225 break;
19226 }
19227
19228 case 0x09: // horizontal tab
19229 {
19230 string_buffer[bytes++] = '\\';
19231 string_buffer[bytes++] = 't';
19232 break;
19233 }
19234
19235 case 0x0A: // newline
19236 {
19237 string_buffer[bytes++] = '\\';
19238 string_buffer[bytes++] = 'n';
19239 break;
19240 }
19241
19242 case 0x0C: // formfeed
19243 {
19244 string_buffer[bytes++] = '\\';
19245 string_buffer[bytes++] = 'f';
19246 break;
19247 }
19248
19249 case 0x0D: // carriage return
19250 {
19251 string_buffer[bytes++] = '\\';
19252 string_buffer[bytes++] = 'r';
19253 break;
19254 }
19255
19256 case 0x22: // quotation mark
19257 {
19258 string_buffer[bytes++] = '\\';
19259 string_buffer[bytes++] = '\"';
19260 break;
19261 }
19262
19263 case 0x5C: // reverse solidus
19264 {
19265 string_buffer[bytes++] = '\\';
19266 string_buffer[bytes++] = '\\';
19267 break;
19268 }
19269
19270 default:
19271 {
19272 // escape control characters (0x00..0x1F) or, if
19273 // ensure_ascii parameter is used, non-ASCII characters
19274 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
19275 {
19276 if (codepoint <= 0xFFFF)
19277 {
19278 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19279 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
19280 static_cast<std::uint16_t>(codepoint)));
19281 bytes += 6;
19282 }
19283 else
19284 {
19285 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19286 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
19287 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
19288 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
19289 bytes += 12;
19290 }
19291 }
19292 else
19293 {
19294 // copy byte to buffer (all previous bytes
19295 // been copied have in default case above)
19296 string_buffer[bytes++] = s[i];
19297 }
19298 break;
19299 }
19300 }
19301
19302 // write buffer and reset index; there must be 13 bytes
19303 // left, as this is the maximal number of bytes to be
19304 // written ("\uxxxx\uxxxx\0") for one code point
19305 if (string_buffer.size() - bytes < 13)
19306 {
19307 o->write_characters(string_buffer.data(), bytes);
19308 bytes = 0;
19309 }
19310
19311 // remember the byte position of this accept
19313 undumped_chars = 0;
19314 break;
19315 }
19316
19317 case UTF8_REJECT: // decode found invalid UTF-8 byte
19318 {
19319 switch (error_handler)
19320 {
19322 {
19323 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
19324 }
19325
19328 {
19329 // in case we saw this character the first time, we
19330 // would like to read it again, because the byte
19331 // may be OK for itself, but just not OK for the
19332 // previous sequence
19333 if (undumped_chars > 0)
19334 {
19335 --i;
19336 }
19337
19338 // reset length buffer to the last accepted index;
19339 // thus removing/ignoring the invalid characters
19341
19343 {
19344 // add a replacement character
19345 if (ensure_ascii)
19346 {
19347 string_buffer[bytes++] = '\\';
19348 string_buffer[bytes++] = 'u';
19349 string_buffer[bytes++] = 'f';
19350 string_buffer[bytes++] = 'f';
19351 string_buffer[bytes++] = 'f';
19352 string_buffer[bytes++] = 'd';
19353 }
19354 else
19355 {
19359 }
19360
19361 // write buffer and reset index; there must be 13 bytes
19362 // left, as this is the maximal number of bytes to be
19363 // written ("\uxxxx\uxxxx\0") for one code point
19364 if (string_buffer.size() - bytes < 13)
19365 {
19366 o->write_characters(string_buffer.data(), bytes);
19367 bytes = 0;
19368 }
19369
19371 }
19372
19373 undumped_chars = 0;
19374
19375 // continue processing the string
19376 state = UTF8_ACCEPT;
19377 break;
19378 }
19379
19380 default: // LCOV_EXCL_LINE
19381 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19382 }
19383 break;
19384 }
19385
19386 default: // decode found yet incomplete multibyte code point
19387 {
19388 if (!ensure_ascii)
19389 {
19390 // code point will not be escaped - copy byte to buffer
19391 string_buffer[bytes++] = s[i];
19392 }
19394 break;
19395 }
19396 }
19397 }
19398
19399 // we finished processing the string
19400 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
19401 {
19402 // write buffer
19403 if (bytes > 0)
19404 {
19405 o->write_characters(string_buffer.data(), bytes);
19406 }
19407 }
19408 else
19409 {
19410 // we finish reading, but do not accept: string was incomplete
19411 switch (error_handler)
19412 {
19414 {
19415 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
19416 }
19417
19419 {
19420 // write all accepted bytes
19421 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19422 break;
19423 }
19424
19426 {
19427 // write all accepted bytes
19428 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19429 // add a replacement character
19430 if (ensure_ascii)
19431 {
19432 o->write_characters("\\ufffd", 6);
19433 }
19434 else
19435 {
19436 o->write_characters("\xEF\xBF\xBD", 3);
19437 }
19438 break;
19439 }
19440
19441 default: // LCOV_EXCL_LINE
19442 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19443 }
19444 }
19445 }
19446
19447 private:
19456 unsigned int count_digits(number_unsigned_t x) noexcept
19457 {
19458 unsigned int n_digits = 1;
19459 for (;;)
19460 {
19461 if (x < 10)
19462 {
19463 return n_digits;
19464 }
19465 if (x < 100)
19466 {
19467 return n_digits + 1;
19468 }
19469 if (x < 1000)
19470 {
19471 return n_digits + 2;
19472 }
19473 if (x < 10000)
19474 {
19475 return n_digits + 3;
19476 }
19477 x = x / 10000u;
19478 n_digits += 4;
19479 }
19480 }
19481
19487 static std::string hex_bytes(std::uint8_t byte)
19488 {
19489 std::string result = "FF";
19490 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
19491 result[0] = nibble_to_hex[byte / 16];
19492 result[1] = nibble_to_hex[byte % 16];
19493 return result;
19494 }
19495
19496 // templates to avoid warnings about useless casts
19497 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
19498 bool is_negative_number(NumberType x)
19499 {
19500 return x < 0;
19501 }
19502
19503 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
19504 bool is_negative_number(NumberType /*unused*/)
19505 {
19506 return false;
19507 }
19508
19518 template < typename NumberType, detail::enable_if_t <
19519 std::is_integral<NumberType>::value ||
19520 std::is_same<NumberType, number_unsigned_t>::value ||
19521 std::is_same<NumberType, number_integer_t>::value ||
19522 std::is_same<NumberType, binary_char_t>::value,
19523 int > = 0 >
19524 void dump_integer(NumberType x)
19525 {
19526 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
19527 {
19528 {
19529 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
19530 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
19531 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
19532 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
19533 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
19534 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
19535 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
19536 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
19537 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
19538 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
19539 }
19540 };
19541
19542 // special case for "0"
19543 if (x == 0)
19544 {
19545 o->write_character('0');
19546 return;
19547 }
19548
19549 // use a pointer to fill the buffer
19550 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19551
19552 number_unsigned_t abs_value;
19553
19554 unsigned int n_chars{};
19555
19556 if (is_negative_number(x))
19557 {
19558 *buffer_ptr = '-';
19559 abs_value = remove_sign(static_cast<number_integer_t>(x));
19560
19561 // account one more byte for the minus sign
19562 n_chars = 1 + count_digits(abs_value);
19563 }
19564 else
19565 {
19566 abs_value = static_cast<number_unsigned_t>(x);
19567 n_chars = count_digits(abs_value);
19568 }
19569
19570 // spare 1 byte for '\0'
19571 JSON_ASSERT(n_chars < number_buffer.size() - 1);
19572
19573 // jump to the end to generate the string from backward,
19574 // so we later avoid reversing the result
19575 buffer_ptr += static_cast<typename decltype(number_buffer)::difference_type>(n_chars);
19576
19577 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
19578 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
19579 while (abs_value >= 100)
19580 {
19581 const auto digits_index = static_cast<unsigned>((abs_value % 100));
19582 abs_value /= 100;
19583 *(--buffer_ptr) = digits_to_99[digits_index][1];
19584 *(--buffer_ptr) = digits_to_99[digits_index][0];
19585 }
19586
19587 if (abs_value >= 10)
19588 {
19589 const auto digits_index = static_cast<unsigned>(abs_value);
19590 *(--buffer_ptr) = digits_to_99[digits_index][1];
19591 *(--buffer_ptr) = digits_to_99[digits_index][0];
19592 }
19593 else
19594 {
19595 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
19596 }
19597
19598 o->write_characters(number_buffer.data(), n_chars);
19599 }
19600
19609 void dump_float(number_float_t x)
19610 {
19611 // NaN / inf
19612 if (!std::isfinite(x))
19613 {
19614 o->write_characters("null", 4);
19615 return;
19616 }
19617
19618 // If number_float_t is an IEEE-754 single or double precision number,
19619 // use the Grisu2 algorithm to produce short numbers which are
19620 // guaranteed to round-trip, using strtof and strtod, resp.
19621 //
19622 // NB: The test below works if <long double> == <double>.
19623 static constexpr bool is_ieee_single_or_double
19624 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
19625 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
19626
19627 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19628 }
19629
19630 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19631 {
19632 auto* begin = number_buffer.data();
19633 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19634
19635 o->write_characters(begin, static_cast<size_t>(end - begin));
19636 }
19637
19638 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19639 {
19640 // get the number of digits for a float -> text -> float round-trip
19641 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19642
19643 // the actual conversion
19644 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19645 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19646
19647 // negative value indicates an error
19648 JSON_ASSERT(len > 0);
19649 // check if the buffer was large enough
19650 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19651
19652 // erase thousands separators
19653 if (thousands_sep != '\0')
19654 {
19655 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19656 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19657 std::fill(end, number_buffer.end(), '\0');
19658 JSON_ASSERT((end - number_buffer.begin()) <= len);
19659 len = (end - number_buffer.begin());
19660 }
19661
19662 // convert decimal point to '.'
19663 if (decimal_point != '\0' && decimal_point != '.')
19664 {
19665 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19666 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19667 if (dec_pos != number_buffer.end())
19668 {
19669 *dec_pos = '.';
19670 }
19671 }
19672
19673 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19674
19675 // determine if we need to append ".0"
19676 const bool value_is_int_like =
19677 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19678 [](char c)
19679 {
19680 return c == '.' || c == 'e';
19681 });
19682
19683 if (value_is_int_like)
19684 {
19685 o->write_characters(".0", 2);
19686 }
19687 }
19688
19710 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19711 {
19712 static const std::array<std::uint8_t, 400> utf8d =
19713 {
19714 {
19715 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
19716 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
19717 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
19718 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
19719 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
19720 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
19721 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
19722 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19723 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19724 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19725 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
19726 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
19727 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
19728 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
19729 }
19730 };
19731
19732 JSON_ASSERT(byte < utf8d.size());
19733 const std::uint8_t type = utf8d[byte];
19734
19735 codep = (state != UTF8_ACCEPT)
19736 ? (byte & 0x3fu) | (codep << 6u)
19737 : (0xFFu >> type) & (byte);
19738
19739 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19740 JSON_ASSERT(index < utf8d.size());
19741 state = utf8d[index];
19742 return state;
19743 }
19744
19745 /*
19746 * Overload to make the compiler happy while it is instantiating
19747 * dump_integer for number_unsigned_t.
19748 * Must never be called.
19749 */
19750 number_unsigned_t remove_sign(number_unsigned_t x)
19751 {
19752 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19753 return x; // LCOV_EXCL_LINE
19754 }
19755
19756 /*
19757 * Helper function for dump_integer
19758 *
19759 * This function takes a negative signed integer and returns its absolute
19760 * value as an unsigned integer. The plus/minus shuffling is necessary as we
19761 * cannot directly remove the sign of an arbitrary signed integer as the
19762 * absolute values of INT_MIN and INT_MAX are usually not the same. See
19763 * #1708 for details.
19764 */
19765 number_unsigned_t remove_sign(number_integer_t x) noexcept
19766 {
19767 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19768 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19769 }
19770
19771 private:
19773 output_adapter_t<char> o = nullptr;
19774
19776 std::array<char, 64> number_buffer{{}};
19777
19779 const std::lconv* loc = nullptr;
19781 const char thousands_sep = '\0';
19783 const char decimal_point = '\0';
19784
19786 std::array<char, 512> string_buffer{{}};
19787
19789 const char indent_char;
19792
19795};
19796
19797} // namespace detail
19799
19800// #include <nlohmann/detail/value_t.hpp>
19801
19802// #include <nlohmann/json_fwd.hpp>
19803
19804// #include <nlohmann/ordered_map.hpp>
19805// __ _____ _____ _____
19806// __| | __| | | | JSON for Modern C++
19807// | | |__ | | | | | | version 3.12.0
19808// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19809//
19810// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
19811// SPDX-License-Identifier: MIT
19812
19813
19814
19815#include <functional> // equal_to, less
19816#include <initializer_list> // initializer_list
19817#include <iterator> // input_iterator_tag, iterator_traits
19818#include <memory> // allocator
19819#include <stdexcept> // for out_of_range
19820#include <type_traits> // enable_if, is_convertible
19821#include <utility> // pair
19822#include <vector> // vector
19823
19824// #include <nlohmann/detail/macro_scope.hpp>
19825
19826// #include <nlohmann/detail/meta/type_traits.hpp>
19827
19828
19830
19833template <class Key, class T, class IgnoredLess = std::less<Key>,
19834 class Allocator = std::allocator<std::pair<const Key, T>>>
19835 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19836{
19837 using key_type = Key;
19838 using mapped_type = T;
19839 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19840 using iterator = typename Container::iterator;
19841 using const_iterator = typename Container::const_iterator;
19842 using size_type = typename Container::size_type;
19843 using value_type = typename Container::value_type;
19844#ifdef JSON_HAS_CPP_14
19845 using key_compare = std::equal_to<>;
19846#else
19847 using key_compare = std::equal_to<Key>;
19848#endif
19849
19850 // Explicit constructors instead of `using Container::Container`
19851 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19852 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19853 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19854 template <class It>
19855 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19856 : Container{first, last, alloc} {}
19857 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19858 : Container{init, alloc} {}
19859
19860 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19861 {
19862 for (auto it = this->begin(); it != this->end(); ++it)
19863 {
19864 if (m_compare(it->first, key))
19865 {
19866 return {it, false};
19867 }
19868 }
19869 Container::emplace_back(key, std::forward<T>(t));
19870 return {std::prev(this->end()), true};
19871 }
19872
19873 template<class KeyType, detail::enable_if_t<
19875 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19876 {
19877 for (auto it = this->begin(); it != this->end(); ++it)
19878 {
19879 if (m_compare(it->first, key))
19880 {
19881 return {it, false};
19882 }
19883 }
19884 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19885 return {std::prev(this->end()), true};
19886 }
19887
19888 T& operator[](const key_type& key)
19889 {
19890 return emplace(key, T{}).first->second;
19891 }
19892
19893 template<class KeyType, detail::enable_if_t<
19895 T & operator[](KeyType && key)
19896 {
19897 return emplace(std::forward<KeyType>(key), T{}).first->second;
19898 }
19899
19900 const T& operator[](const key_type& key) const
19901 {
19902 return at(key);
19903 }
19904
19905 template<class KeyType, detail::enable_if_t<
19907 const T & operator[](KeyType && key) const
19908 {
19909 return at(std::forward<KeyType>(key));
19910 }
19911
19912 T& at(const key_type& key)
19913 {
19914 for (auto it = this->begin(); it != this->end(); ++it)
19915 {
19916 if (m_compare(it->first, key))
19917 {
19918 return it->second;
19919 }
19920 }
19921
19922 JSON_THROW(std::out_of_range("key not found"));
19923 }
19924
19925 template<class KeyType, detail::enable_if_t<
19927 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19928 {
19929 for (auto it = this->begin(); it != this->end(); ++it)
19930 {
19931 if (m_compare(it->first, key))
19932 {
19933 return it->second;
19934 }
19935 }
19936
19937 JSON_THROW(std::out_of_range("key not found"));
19938 }
19939
19940 const T& at(const key_type& key) const
19941 {
19942 for (auto it = this->begin(); it != this->end(); ++it)
19943 {
19944 if (m_compare(it->first, key))
19945 {
19946 return it->second;
19947 }
19948 }
19949
19950 JSON_THROW(std::out_of_range("key not found"));
19951 }
19952
19953 template<class KeyType, detail::enable_if_t<
19955 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19956 {
19957 for (auto it = this->begin(); it != this->end(); ++it)
19958 {
19959 if (m_compare(it->first, key))
19960 {
19961 return it->second;
19962 }
19963 }
19964
19965 JSON_THROW(std::out_of_range("key not found"));
19966 }
19967
19969 {
19970 for (auto it = this->begin(); it != this->end(); ++it)
19971 {
19972 if (m_compare(it->first, key))
19973 {
19974 // Since we cannot move const Keys, re-construct them in place
19975 for (auto next = it; ++next != this->end(); ++it)
19976 {
19977 it->~value_type(); // Destroy but keep allocation
19978 new (&*it) value_type{std::move(*next)};
19979 }
19980 Container::pop_back();
19981 return 1;
19982 }
19983 }
19984 return 0;
19985 }
19986
19987 template<class KeyType, detail::enable_if_t<
19989 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19990 {
19991 for (auto it = this->begin(); it != this->end(); ++it)
19992 {
19993 if (m_compare(it->first, key))
19994 {
19995 // Since we cannot move const Keys, re-construct them in place
19996 for (auto next = it; ++next != this->end(); ++it)
19997 {
19998 it->~value_type(); // Destroy but keep allocation
19999 new (&*it) value_type{std::move(*next)};
20000 }
20001 Container::pop_back();
20002 return 1;
20003 }
20004 }
20005 return 0;
20006 }
20007
20009 {
20010 return erase(pos, std::next(pos));
20011 }
20012
20014 {
20015 if (first == last)
20016 {
20017 return first;
20018 }
20019
20020 const auto elements_affected = std::distance(first, last);
20021 const auto offset = std::distance(Container::begin(), first);
20022
20023 // This is the start situation. We need to delete elements_affected
20024 // elements (3 in this example: e, f, g), and need to return an
20025 // iterator past the last deleted element (h in this example).
20026 // Note that offset is the distance from the start of the vector
20027 // to first. We will need this later.
20028
20029 // [ a, b, c, d, e, f, g, h, i, j ]
20030 // ^ ^
20031 // first last
20032
20033 // Since we cannot move const Keys, we re-construct them in place.
20034 // We start at first and re-construct (viz. copy) the elements from
20035 // the back of the vector. Example for the first iteration:
20036
20037 // ,--------.
20038 // v | destroy e and re-construct with h
20039 // [ a, b, c, d, e, f, g, h, i, j ]
20040 // ^ ^
20041 // it it + elements_affected
20042
20043 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
20044 {
20045 it->~value_type(); // destroy but keep allocation
20046 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
20047 }
20048
20049 // [ a, b, c, d, h, i, j, h, i, j ]
20050 // ^ ^
20051 // first last
20052
20053 // remove the unneeded elements at the end of the vector
20054 Container::resize(this->size() - static_cast<size_type>(elements_affected));
20055
20056 // [ a, b, c, d, h, i, j ]
20057 // ^ ^
20058 // first last
20059
20060 // first is now pointing past the last deleted element, but we cannot
20061 // use this iterator, because it may have been invalidated by the
20062 // resize call. Instead, we can return begin() + offset.
20063 return Container::begin() + offset;
20064 }
20065
20066 size_type count(const key_type& key) const
20067 {
20068 for (auto it = this->begin(); it != this->end(); ++it)
20069 {
20070 if (m_compare(it->first, key))
20071 {
20072 return 1;
20073 }
20074 }
20075 return 0;
20076 }
20077
20078 template<class KeyType, detail::enable_if_t<
20080 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
20081 {
20082 for (auto it = this->begin(); it != this->end(); ++it)
20083 {
20084 if (m_compare(it->first, key))
20085 {
20086 return 1;
20087 }
20088 }
20089 return 0;
20090 }
20091
20093 {
20094 for (auto it = this->begin(); it != this->end(); ++it)
20095 {
20096 if (m_compare(it->first, key))
20097 {
20098 return it;
20099 }
20100 }
20101 return Container::end();
20102 }
20103
20104 template<class KeyType, detail::enable_if_t<
20106 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20107 {
20108 for (auto it = this->begin(); it != this->end(); ++it)
20109 {
20110 if (m_compare(it->first, key))
20111 {
20112 return it;
20113 }
20114 }
20115 return Container::end();
20116 }
20117
20118 const_iterator find(const key_type& key) const
20119 {
20120 for (auto it = this->begin(); it != this->end(); ++it)
20121 {
20122 if (m_compare(it->first, key))
20123 {
20124 return it;
20125 }
20126 }
20127 return Container::end();
20128 }
20129
20130 std::pair<iterator, bool> insert( value_type&& value )
20131 {
20132 return emplace(value.first, std::move(value.second));
20133 }
20134
20135 std::pair<iterator, bool> insert( const value_type& value )
20136 {
20137 for (auto it = this->begin(); it != this->end(); ++it)
20138 {
20139 if (m_compare(it->first, value.first))
20140 {
20141 return {it, false};
20142 }
20143 }
20144 Container::push_back(value);
20145 return {--this->end(), true};
20146 }
20147
20148 template<typename InputIt>
20149 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
20150 std::input_iterator_tag>::value>::type;
20151
20152 template<typename InputIt, typename = require_input_iter<InputIt>>
20153 void insert(InputIt first, InputIt last)
20154 {
20155 for (auto it = first; it != last; ++it)
20156 {
20157 insert(*it);
20158 }
20159 }
20160
20161private:
20162 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
20163};
20164
20166
20167
20168#if defined(JSON_HAS_CPP_17)
20169 #if JSON_HAS_STATIC_RTTI
20170 #include <any>
20171 #endif
20172 #include <string_view>
20173#endif
20174
20181
20201class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
20202 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
20203{
20204 private:
20205 template<detail::value_t> friend struct detail::external_constructor;
20206
20207 template<typename>
20208 friend class ::nlohmann::json_pointer;
20209 // can be restored when json_pointer backwards compatibility is removed
20210 // friend ::nlohmann::json_pointer<StringType>;
20211
20212 template<typename BasicJsonType, typename InputType>
20213 friend class ::nlohmann::detail::parser;
20214 friend ::nlohmann::detail::serializer<basic_json>;
20215 template<typename BasicJsonType>
20216 friend class ::nlohmann::detail::iter_impl;
20217 template<typename BasicJsonType, typename CharType>
20218 friend class ::nlohmann::detail::binary_writer;
20219 template<typename BasicJsonType, typename InputType, typename SAX>
20220 friend class ::nlohmann::detail::binary_reader;
20221 template<typename BasicJsonType, typename InputAdapterType>
20222 friend class ::nlohmann::detail::json_sax_dom_parser;
20223 template<typename BasicJsonType, typename InputAdapterType>
20224 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
20225 friend class ::nlohmann::detail::exception;
20226
20228 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
20229 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
20230
20232 // convenience aliases for types residing in namespace detail;
20233 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
20234
20235 template<typename InputAdapterType>
20236 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
20237 InputAdapterType adapter,
20239 const bool allow_exceptions = true,
20240 const bool ignore_comments = false,
20241 const bool ignore_trailing_commas = false
20242 )
20243 {
20244 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
20245 std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
20246 }
20247
20248 private:
20249 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
20250 template<typename BasicJsonType>
20251 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
20252 template<typename BasicJsonType>
20253 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
20254 template<typename Iterator>
20255 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
20256 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
20257
20258 template<typename CharType>
20259 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
20260
20261 template<typename InputType>
20262 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
20263 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
20264
20266 using serializer = ::nlohmann::detail::serializer<basic_json>;
20267
20268 public:
20271 using json_pointer = ::nlohmann::json_pointer<StringType>;
20272 template<typename T, typename SFINAE>
20273 using json_serializer = JSONSerializer<T, SFINAE>;
20281 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
20282
20286
20288 // exceptions //
20290
20294
20301
20303
20305 // container types //
20307
20312
20315
20320
20322 using difference_type = std::ptrdiff_t;
20324 using size_type = std::size_t;
20325
20327 using allocator_type = AllocatorType<basic_json>;
20328
20330 using pointer = typename std::allocator_traits<allocator_type>::pointer;
20332 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
20333
20335 using iterator = iter_impl<basic_json>;
20337 using const_iterator = iter_impl<const basic_json>;
20339 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
20341 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
20342
20344
20348 {
20349 return allocator_type();
20350 }
20351
20356 {
20357 basic_json result;
20358
20359 result["copyright"] = "(C) 2013-2025 Niels Lohmann";
20360 result["name"] = "JSON for Modern C++";
20361 result["url"] = "https://github.com/nlohmann/json";
20362 result["version"]["string"] =
20363 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
20364 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
20365 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
20366 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
20367 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
20368 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
20369
20370#ifdef _WIN32
20371 result["platform"] = "win32";
20372#elif defined __linux__
20373 result["platform"] = "linux";
20374#elif defined __APPLE__
20375 result["platform"] = "apple";
20376#elif defined __unix__
20377 result["platform"] = "unix";
20378#else
20379 result["platform"] = "unknown";
20380#endif
20381
20382#if defined(__ICC) || defined(__INTEL_COMPILER)
20383 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
20384#elif defined(__clang__)
20385 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
20386#elif defined(__GNUC__) || defined(__GNUG__)
20387 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
20388 std::to_string(__GNUC__), '.',
20389 std::to_string(__GNUC_MINOR__), '.',
20390 std::to_string(__GNUC_PATCHLEVEL__))
20391 }
20392 };
20393#elif defined(__HP_cc) || defined(__HP_aCC)
20394 result["compiler"] = "hp"
20395#elif defined(__IBMCPP__)
20396 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
20397#elif defined(_MSC_VER)
20398 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
20399#elif defined(__PGI)
20400 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
20401#elif defined(__SUNPRO_CC)
20402 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
20403#else
20404 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
20405#endif
20406
20407#if defined(_MSVC_LANG)
20408 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
20409#elif defined(__cplusplus)
20410 result["compiler"]["c++"] = std::to_string(__cplusplus);
20411#else
20412 result["compiler"]["c++"] = "unknown";
20413#endif
20414 return result;
20415 }
20416
20418 // JSON value data types //
20420
20425
20430#if defined(JSON_HAS_CPP_14)
20431 // use of transparent comparator avoids unnecessary repeated construction of temporaries
20432 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
20433 using default_object_comparator_t = std::less<>;
20434#else
20435 using default_object_comparator_t = std::less<StringType>;
20436#endif
20437
20440 using object_t = ObjectType<StringType,
20441 basic_json,
20443 AllocatorType<std::pair<const StringType,
20444 basic_json>>>;
20445
20448 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
20449
20452 using string_t = StringType;
20453
20456 using boolean_t = BooleanType;
20457
20460 using number_integer_t = NumberIntegerType;
20461
20464 using number_unsigned_t = NumberUnsignedType;
20465
20468 using number_float_t = NumberFloatType;
20469
20472 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
20473
20477
20479
20480 private:
20481
20483 template<typename T, typename... Args>
20485 static T* create(Args&& ... args)
20486 {
20487 AllocatorType<T> alloc;
20488 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
20489
20490 auto deleter = [&](T * obj)
20491 {
20492 AllocatorTraits::deallocate(alloc, obj, 1);
20493 };
20494 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
20495 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
20496 JSON_ASSERT(obj != nullptr);
20497 return obj.release();
20498 }
20499
20501 // JSON value storage //
20503
20530 union json_value
20531 {
20533 object_t* object;
20535 array_t* array;
20537 string_t* string;
20539 binary_t* binary;
20541 boolean_t boolean;
20543 number_integer_t number_integer;
20545 number_unsigned_t number_unsigned;
20547 number_float_t number_float;
20548
20550 json_value() = default;
20552 json_value(boolean_t v) noexcept : boolean(v) {}
20554 json_value(number_integer_t v) noexcept : number_integer(v) {}
20556 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
20558 json_value(number_float_t v) noexcept : number_float(v) {}
20560 json_value(value_t t)
20561 {
20562 switch (t)
20563 {
20564 case value_t::object:
20565 {
20566 object = create<object_t>();
20567 break;
20568 }
20569
20570 case value_t::array:
20571 {
20572 array = create<array_t>();
20573 break;
20574 }
20575
20576 case value_t::string:
20577 {
20578 string = create<string_t>("");
20579 break;
20580 }
20581
20582 case value_t::binary:
20583 {
20584 binary = create<binary_t>();
20585 break;
20586 }
20587
20588 case value_t::boolean:
20589 {
20590 boolean = static_cast<boolean_t>(false);
20591 break;
20592 }
20593
20594 case value_t::number_integer:
20595 {
20596 number_integer = static_cast<number_integer_t>(0);
20597 break;
20598 }
20599
20600 case value_t::number_unsigned:
20601 {
20602 number_unsigned = static_cast<number_unsigned_t>(0);
20603 break;
20604 }
20605
20606 case value_t::number_float:
20607 {
20608 number_float = static_cast<number_float_t>(0.0);
20609 break;
20610 }
20611
20612 case value_t::null:
20613 {
20614 object = nullptr; // silence warning, see #821
20615 break;
20616 }
20617
20618 case value_t::discarded:
20619 default:
20620 {
20621 object = nullptr; // silence warning, see #821
20622 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20623 {
20624 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
20625 }
20626 break;
20627 }
20628 }
20629 }
20630
20632 json_value(const string_t& value) : string(create<string_t>(value)) {}
20633
20635 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
20636
20638 json_value(const object_t& value) : object(create<object_t>(value)) {}
20639
20641 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
20642
20644 json_value(const array_t& value) : array(create<array_t>(value)) {}
20645
20647 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
20648
20650 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20651
20653 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20654
20656 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
20657
20659 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
20660
20661 void destroy(value_t t)
20662 {
20663 if (
20664 (t == value_t::object && object == nullptr) ||
20665 (t == value_t::array && array == nullptr) ||
20666 (t == value_t::string && string == nullptr) ||
20667 (t == value_t::binary && binary == nullptr)
20668 )
20669 {
20670 // not initialized (e.g., due to exception in the ctor)
20671 return;
20672 }
20673 if (t == value_t::array || t == value_t::object)
20674 {
20675 // flatten the current json_value to a heap-allocated stack
20676 std::vector<basic_json> stack;
20677
20678 // move the top-level items to stack
20679 if (t == value_t::array)
20680 {
20681 stack.reserve(array->size());
20682 std::move(array->begin(), array->end(), std::back_inserter(stack));
20683 }
20684 else
20685 {
20686 stack.reserve(object->size());
20687 for (auto&& it : *object)
20688 {
20689 stack.push_back(std::move(it.second));
20690 }
20691 }
20692
20693 while (!stack.empty())
20694 {
20695 // move the last item to a local variable to be processed
20696 basic_json current_item(std::move(stack.back()));
20697 stack.pop_back();
20698
20699 // if current_item is array/object, move
20700 // its children to the stack to be processed later
20701 if (current_item.is_array())
20702 {
20703 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20704
20705 current_item.m_data.m_value.array->clear();
20706 }
20707 else if (current_item.is_object())
20708 {
20709 for (auto&& it : *current_item.m_data.m_value.object)
20710 {
20711 stack.push_back(std::move(it.second));
20712 }
20713
20714 current_item.m_data.m_value.object->clear();
20715 }
20716
20717 // it's now safe that current_item gets destructed
20718 // since it doesn't have any children
20719 }
20720 }
20721
20722 switch (t)
20723 {
20724 case value_t::object:
20725 {
20726 AllocatorType<object_t> alloc;
20727 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20728 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20729 break;
20730 }
20731
20732 case value_t::array:
20733 {
20734 AllocatorType<array_t> alloc;
20735 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20736 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20737 break;
20738 }
20739
20740 case value_t::string:
20741 {
20742 AllocatorType<string_t> alloc;
20743 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20744 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20745 break;
20746 }
20747
20748 case value_t::binary:
20749 {
20750 AllocatorType<binary_t> alloc;
20751 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20752 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20753 break;
20754 }
20755
20756 case value_t::null:
20757 case value_t::boolean:
20758 case value_t::number_integer:
20759 case value_t::number_unsigned:
20760 case value_t::number_float:
20761 case value_t::discarded:
20762 default:
20763 {
20764 break;
20765 }
20766 }
20767 }
20768 };
20769
20770 private:
20789 void assert_invariant(bool check_parents = true) const noexcept
20790 {
20791 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20792 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20793 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20794 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20795
20796#if JSON_DIAGNOSTICS
20797 JSON_TRY
20798 {
20799 // cppcheck-suppress assertWithSideEffect
20800 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20801 {
20802 return j.m_parent == this;
20803 }));
20804 }
20805 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20806#endif
20807 static_cast<void>(check_parents);
20808 }
20809
20810 void set_parents()
20811 {
20812#if JSON_DIAGNOSTICS
20813 switch (m_data.m_type)
20814 {
20815 case value_t::array:
20816 {
20817 for (auto& element : *m_data.m_value.array)
20818 {
20819 element.m_parent = this;
20820 }
20821 break;
20822 }
20823
20824 case value_t::object:
20825 {
20826 for (auto& element : *m_data.m_value.object)
20827 {
20828 element.second.m_parent = this;
20829 }
20830 break;
20831 }
20832
20833 case value_t::null:
20834 case value_t::string:
20835 case value_t::boolean:
20836 case value_t::number_integer:
20837 case value_t::number_unsigned:
20838 case value_t::number_float:
20839 case value_t::binary:
20840 case value_t::discarded:
20841 default:
20842 break;
20843 }
20844#endif
20845 }
20846
20847 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20848 {
20849#if JSON_DIAGNOSTICS
20850 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20851 {
20852 (it + i)->m_parent = this;
20853 }
20854#else
20855 static_cast<void>(count_set_parents);
20856#endif
20857 return it;
20858 }
20859
20860 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
20861 {
20862#if JSON_DIAGNOSTICS
20863 if (old_capacity != detail::unknown_size())
20864 {
20865 // see https://github.com/nlohmann/json/issues/2838
20866 JSON_ASSERT(type() == value_t::array);
20867 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20868 {
20869 // capacity has changed: update all parents
20870 set_parents();
20871 return j;
20872 }
20873 }
20874
20875 // ordered_json uses a vector internally, so pointers could have
20876 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20877#ifdef JSON_HEDLEY_MSVC_VERSION
20878#pragma warning(push )
20879#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20880#endif
20882 {
20883 set_parents();
20884 return j;
20885 }
20886#ifdef JSON_HEDLEY_MSVC_VERSION
20887#pragma warning( pop )
20888#endif
20889
20890 j.m_parent = this;
20891#else
20892 static_cast<void>(j);
20893 static_cast<void>(old_capacity);
20894#endif
20895 return j;
20896 }
20897
20898 public:
20900 // JSON parser callback //
20902
20906
20910
20912 // constructors //
20914
20919
20923 : m_data(v)
20924 {
20925 assert_invariant();
20926 }
20927
20930 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20931 : basic_json(value_t::null)
20932 {
20933 assert_invariant();
20934 }
20935
20938 template < typename CompatibleType,
20942 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20943 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20944 std::forward<CompatibleType>(val))))
20945 {
20946 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20947 set_parents();
20948 assert_invariant();
20949 }
20950
20953 template < typename BasicJsonType,
20955 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20956 basic_json(const BasicJsonType& val)
20957#if JSON_DIAGNOSTIC_POSITIONS
20958 : start_position(val.start_pos()),
20959 end_position(val.end_pos())
20960#endif
20961 {
20962 using other_boolean_t = typename BasicJsonType::boolean_t;
20963 using other_number_float_t = typename BasicJsonType::number_float_t;
20964 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20965 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20966 using other_string_t = typename BasicJsonType::string_t;
20967 using other_object_t = typename BasicJsonType::object_t;
20968 using other_array_t = typename BasicJsonType::array_t;
20969 using other_binary_t = typename BasicJsonType::binary_t;
20970
20971 switch (val.type())
20972 {
20973 case value_t::boolean:
20974 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20975 break;
20976 case value_t::number_float:
20977 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20978 break;
20979 case value_t::number_integer:
20980 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20981 break;
20982 case value_t::number_unsigned:
20983 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20984 break;
20985 case value_t::string:
20986 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20987 break;
20988 case value_t::object:
20989 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20990 break;
20991 case value_t::array:
20992 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20993 break;
20994 case value_t::binary:
20995 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20996 break;
20997 case value_t::null:
20998 *this = nullptr;
20999 break;
21000 case value_t::discarded:
21001 m_data.m_type = value_t::discarded;
21002 break;
21003 default: // LCOV_EXCL_LINE
21004 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
21005 }
21006 JSON_ASSERT(m_data.m_type == val.type());
21007
21008 set_parents();
21009 assert_invariant();
21010 }
21011
21015 bool type_deduction = true,
21016 value_t manual_type = value_t::array)
21017 {
21018 // check if each element is an array with two elements whose first
21019 // element is a string
21020 bool is_an_object = std::all_of(init.begin(), init.end(),
21021 [](const detail::json_ref<basic_json>& element_ref)
21022 {
21023 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
21024 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
21025 // broken call to op[key_type], the wrong semantics, and a 4804 warning on Windows)
21026 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
21027 });
21028
21029 // adjust type if type deduction is not wanted
21030 if (!type_deduction)
21031 {
21032 // if an array is wanted, do not create an object though possible
21033 if (manual_type == value_t::array)
21034 {
21035 is_an_object = false;
21036 }
21037
21038 // if an object is wanted but impossible, throw an exception
21039 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
21040 {
21041 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
21042 }
21043 }
21044
21045 if (is_an_object)
21046 {
21047 // the initializer list is a list of pairs -> create an object
21048 m_data.m_type = value_t::object;
21049 m_data.m_value = value_t::object;
21050
21051 for (auto& element_ref : init)
21052 {
21053 auto element = element_ref.moved_or_copied();
21054 m_data.m_value.object->emplace(
21055 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
21056 std::move((*element.m_data.m_value.array)[1]));
21057 }
21058 }
21059 else
21060 {
21061 // the initializer list describes an array -> create an array
21062 m_data.m_type = value_t::array;
21063 m_data.m_value.array = create<array_t>(init.begin(), init.end());
21064 }
21065
21066 set_parents();
21067 assert_invariant();
21068 }
21069
21073 static basic_json binary(const typename binary_t::container_type& init)
21074 {
21075 auto res = basic_json();
21076 res.m_data.m_type = value_t::binary;
21077 res.m_data.m_value = init;
21078 return res;
21079 }
21080
21084 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
21085 {
21086 auto res = basic_json();
21087 res.m_data.m_type = value_t::binary;
21088 res.m_data.m_value = binary_t(init, subtype);
21089 return res;
21090 }
21091
21095 static basic_json binary(typename binary_t::container_type&& init)
21096 {
21097 auto res = basic_json();
21098 res.m_data.m_type = value_t::binary;
21099 res.m_data.m_value = std::move(init);
21100 return res;
21101 }
21102
21106 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
21107 {
21108 auto res = basic_json();
21109 res.m_data.m_type = value_t::binary;
21110 res.m_data.m_value = binary_t(std::move(init), subtype);
21111 return res;
21112 }
21113
21118 {
21119 return basic_json(init, false, value_t::array);
21120 }
21121
21126 {
21127 return basic_json(init, false, value_t::object);
21128 }
21129
21133 m_data{cnt, val}
21134 {
21135 set_parents();
21136 assert_invariant();
21137 }
21138
21141 template < class InputIT, typename std::enable_if <
21142 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
21143 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
21144 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
21145 {
21146 JSON_ASSERT(first.m_object != nullptr);
21147 JSON_ASSERT(last.m_object != nullptr);
21148
21149 // make sure the iterator fits the current value
21150 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21151 {
21152 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
21153 }
21154
21155 // copy type from the first iterator
21156 m_data.m_type = first.m_object->m_data.m_type;
21157
21158 // check if the iterator range is complete for primitive values
21159 switch (m_data.m_type)
21160 {
21161 case value_t::boolean:
21162 case value_t::number_float:
21163 case value_t::number_integer:
21164 case value_t::number_unsigned:
21165 case value_t::string:
21166 {
21167 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
21168 || !last.m_it.primitive_iterator.is_end()))
21169 {
21170 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
21171 }
21172 break;
21173 }
21174
21175 case value_t::null:
21176 case value_t::object:
21177 case value_t::array:
21178 case value_t::binary:
21179 case value_t::discarded:
21180 default:
21181 break;
21182 }
21183
21184 switch (m_data.m_type)
21185 {
21186 case value_t::number_integer:
21187 {
21188 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
21189 break;
21190 }
21191
21192 case value_t::number_unsigned:
21193 {
21194 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
21195 break;
21196 }
21197
21198 case value_t::number_float:
21199 {
21200 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
21201 break;
21202 }
21203
21204 case value_t::boolean:
21205 {
21206 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
21207 break;
21208 }
21209
21210 case value_t::string:
21211 {
21212 m_data.m_value = *first.m_object->m_data.m_value.string;
21213 break;
21214 }
21215
21216 case value_t::object:
21217 {
21218 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
21219 last.m_it.object_iterator);
21220 break;
21221 }
21222
21223 case value_t::array:
21224 {
21225 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
21226 last.m_it.array_iterator);
21227 break;
21228 }
21229
21230 case value_t::binary:
21231 {
21232 m_data.m_value = *first.m_object->m_data.m_value.binary;
21233 break;
21234 }
21235
21236 case value_t::null:
21237 case value_t::discarded:
21238 default:
21239 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
21240 }
21241
21242 set_parents();
21243 assert_invariant();
21244 }
21245
21247 // other constructors and destructor //
21249
21250 template<typename JsonRef,
21252 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
21253 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
21254
21258 : json_base_class_t(other)
21260 , start_position(other.start_position)
21261 , end_position(other.end_position)
21262#endif
21263 {
21264 m_data.m_type = other.m_data.m_type;
21265 // check of passed value is valid
21266 other.assert_invariant();
21267
21268 switch (m_data.m_type)
21269 {
21270 case value_t::object:
21271 {
21272 m_data.m_value = *other.m_data.m_value.object;
21273 break;
21274 }
21275
21276 case value_t::array:
21277 {
21278 m_data.m_value = *other.m_data.m_value.array;
21279 break;
21280 }
21281
21282 case value_t::string:
21283 {
21284 m_data.m_value = *other.m_data.m_value.string;
21285 break;
21286 }
21287
21288 case value_t::boolean:
21289 {
21290 m_data.m_value = other.m_data.m_value.boolean;
21291 break;
21292 }
21293
21294 case value_t::number_integer:
21295 {
21296 m_data.m_value = other.m_data.m_value.number_integer;
21297 break;
21298 }
21299
21300 case value_t::number_unsigned:
21301 {
21302 m_data.m_value = other.m_data.m_value.number_unsigned;
21303 break;
21304 }
21305
21306 case value_t::number_float:
21307 {
21308 m_data.m_value = other.m_data.m_value.number_float;
21309 break;
21310 }
21311
21312 case value_t::binary:
21313 {
21314 m_data.m_value = *other.m_data.m_value.binary;
21315 break;
21316 }
21317
21318 case value_t::null:
21319 case value_t::discarded:
21320 default:
21321 break;
21322 }
21323
21324 set_parents();
21325 assert_invariant();
21326 }
21327
21330 basic_json(basic_json&& other) noexcept
21331 : json_base_class_t(std::forward<json_base_class_t>(other)),
21332 m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
21333#if JSON_DIAGNOSTIC_POSITIONS
21334 , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
21335 , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
21336#endif
21337 {
21338 // check that the passed value is valid
21339 other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
21340
21341 // invalidate payload
21342 other.m_data.m_type = value_t::null;
21343 other.m_data.m_value = {};
21344
21345#if JSON_DIAGNOSTIC_POSITIONS
21346 other.start_position = std::string::npos;
21347 other.end_position = std::string::npos;
21348#endif
21349
21350 set_parents();
21351 assert_invariant();
21352 }
21353
21357 std::is_nothrow_move_constructible<value_t>::value&&
21358 std::is_nothrow_move_assignable<value_t>::value&&
21359 std::is_nothrow_move_constructible<json_value>::value&&
21360 std::is_nothrow_move_assignable<json_value>::value&&
21361 std::is_nothrow_move_assignable<json_base_class_t>::value
21362 )
21363 {
21364 // check that the passed value is valid
21365 other.assert_invariant();
21366
21367 using std::swap;
21368 swap(m_data.m_type, other.m_data.m_type);
21369 swap(m_data.m_value, other.m_data.m_value);
21370
21371#if JSON_DIAGNOSTIC_POSITIONS
21372 swap(start_position, other.start_position);
21373 swap(end_position, other.end_position);
21374#endif
21375
21376 json_base_class_t::operator=(std::move(other));
21377
21378 set_parents();
21379 assert_invariant();
21380 return *this;
21381 }
21382
21385 ~basic_json() noexcept
21386 {
21387 assert_invariant(false);
21388 }
21389
21391
21392 public:
21394 // object inspection //
21396
21400
21403 string_t dump(const int indent = -1,
21404 const char indent_char = ' ',
21405 const bool ensure_ascii = false,
21406 const error_handler_t error_handler = error_handler_t::strict) const
21407 {
21408 string_t result;
21409 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
21410
21411 if (indent >= 0)
21412 {
21413 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
21414 }
21415 else
21416 {
21417 s.dump(*this, false, ensure_ascii, 0);
21418 }
21419
21420 return result;
21421 }
21422
21425 constexpr value_t type() const noexcept
21426 {
21427 return m_data.m_type;
21428 }
21429
21432 constexpr bool is_primitive() const noexcept
21433 {
21434 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
21435 }
21436
21439 constexpr bool is_structured() const noexcept
21440 {
21441 return is_array() || is_object();
21442 }
21443
21446 constexpr bool is_null() const noexcept
21447 {
21448 return m_data.m_type == value_t::null;
21449 }
21450
21453 constexpr bool is_boolean() const noexcept
21454 {
21455 return m_data.m_type == value_t::boolean;
21456 }
21457
21460 constexpr bool is_number() const noexcept
21461 {
21462 return is_number_integer() || is_number_float();
21463 }
21464
21467 constexpr bool is_number_integer() const noexcept
21468 {
21469 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
21470 }
21471
21474 constexpr bool is_number_unsigned() const noexcept
21475 {
21476 return m_data.m_type == value_t::number_unsigned;
21477 }
21478
21481 constexpr bool is_number_float() const noexcept
21482 {
21483 return m_data.m_type == value_t::number_float;
21484 }
21485
21488 constexpr bool is_object() const noexcept
21489 {
21490 return m_data.m_type == value_t::object;
21491 }
21492
21495 constexpr bool is_array() const noexcept
21496 {
21497 return m_data.m_type == value_t::array;
21498 }
21499
21502 constexpr bool is_string() const noexcept
21503 {
21504 return m_data.m_type == value_t::string;
21505 }
21506
21509 constexpr bool is_binary() const noexcept
21510 {
21511 return m_data.m_type == value_t::binary;
21512 }
21513
21516 constexpr bool is_discarded() const noexcept
21517 {
21518 return m_data.m_type == value_t::discarded;
21519 }
21520
21523 constexpr operator value_t() const noexcept
21524 {
21525 return m_data.m_type;
21526 }
21527
21529
21530 private:
21532 // value access //
21534
21536 boolean_t get_impl(boolean_t* /*unused*/) const
21537 {
21538 if (JSON_HEDLEY_LIKELY(is_boolean()))
21539 {
21540 return m_data.m_value.boolean;
21541 }
21542
21543 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
21544 }
21545
21547 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
21548 {
21549 return is_object() ? m_data.m_value.object : nullptr;
21550 }
21551
21553 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
21554 {
21555 return is_object() ? m_data.m_value.object : nullptr;
21556 }
21557
21559 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
21560 {
21561 return is_array() ? m_data.m_value.array : nullptr;
21562 }
21563
21565 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
21566 {
21567 return is_array() ? m_data.m_value.array : nullptr;
21568 }
21569
21571 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
21572 {
21573 return is_string() ? m_data.m_value.string : nullptr;
21574 }
21575
21577 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
21578 {
21579 return is_string() ? m_data.m_value.string : nullptr;
21580 }
21581
21583 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
21584 {
21585 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21586 }
21587
21589 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
21590 {
21591 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21592 }
21593
21595 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
21596 {
21597 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21598 }
21599
21601 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
21602 {
21603 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21604 }
21605
21607 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
21608 {
21609 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21610 }
21611
21613 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
21614 {
21615 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21616 }
21617
21619 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
21620 {
21621 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21622 }
21623
21625 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
21626 {
21627 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21628 }
21629
21631 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21632 {
21633 return is_binary() ? m_data.m_value.binary : nullptr;
21634 }
21635
21637 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21638 {
21639 return is_binary() ? m_data.m_value.binary : nullptr;
21640 }
21641
21653 template<typename ReferenceType, typename ThisType>
21654 static ReferenceType get_ref_impl(ThisType& obj)
21655 {
21656 // delegate the call to get_ptr<>()
21657 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
21658
21659 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21660 {
21661 return *ptr;
21662 }
21663
21664 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21665 }
21666
21667 public:
21671
21674 template<typename PointerType, typename std::enable_if<
21675 std::is_pointer<PointerType>::value, int>::type = 0>
21676 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21677 {
21678 // delegate the call to get_impl_ptr<>()
21679 return get_impl_ptr(static_cast<PointerType>(nullptr));
21680 }
21681
21684 template < typename PointerType, typename std::enable_if <
21685 std::is_pointer<PointerType>::value&&
21686 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21687 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21688 {
21689 // delegate the call to get_impl_ptr<>() const
21690 return get_impl_ptr(static_cast<PointerType>(nullptr));
21691 }
21692
21693 private:
21732 template < typename ValueType,
21736 int > = 0 >
21737 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21738 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21739 {
21740 auto ret = ValueType();
21741 JSONSerializer<ValueType>::from_json(*this, ret);
21742 return ret;
21743 }
21744
21775 template < typename ValueType,
21777 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
21778 int > = 0 >
21779 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21780 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21781 {
21782 return JSONSerializer<ValueType>::from_json(*this);
21783 }
21784
21800 template < typename BasicJsonType,
21802 detail::is_basic_json<BasicJsonType>::value,
21803 int > = 0 >
21804 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21805 {
21806 return *this;
21807 }
21808
21823 template<typename BasicJsonType,
21825 std::is_same<BasicJsonType, basic_json_t>::value,
21826 int> = 0>
21827 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21828 {
21829 return *this;
21830 }
21831
21836 template<typename PointerType,
21838 std::is_pointer<PointerType>::value,
21839 int> = 0>
21840 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21841 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21842 {
21843 // delegate the call to get_ptr
21844 return get_ptr<PointerType>();
21845 }
21846
21847 public:
21871 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21872#if defined(JSON_HAS_CPP_14)
21873 constexpr
21874#endif
21875 auto get() const noexcept(
21876 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21877 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21878 {
21879 // we cannot static_assert on ValueTypeCV being non-const, because
21880 // there is support for get<const basic_json_t>(), which is why we
21881 // still need the uncvref
21882 static_assert(!std::is_reference<ValueTypeCV>::value,
21883 "get() cannot be used with reference types, you might want to use get_ref()");
21884 return get_impl<ValueType>(detail::priority_tag<4> {});
21885 }
21886
21914 template<typename PointerType, typename std::enable_if<
21915 std::is_pointer<PointerType>::value, int>::type = 0>
21916 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21917 {
21918 // delegate the call to get_ptr
21919 return get_ptr<PointerType>();
21920 }
21921
21924 template < typename ValueType,
21928 int > = 0 >
21929 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21930 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21931 {
21932 JSONSerializer<ValueType>::from_json(*this, v);
21933 return v;
21934 }
21935
21936 // specialization to allow calling get_to with a basic_json value
21937 // see https://github.com/nlohmann/json/issues/2175
21938 template<typename ValueType,
21941 int> = 0>
21942 ValueType & get_to(ValueType& v) const
21943 {
21944 v = *this;
21945 return v;
21946 }
21947
21948 template <
21949 typename T, std::size_t N,
21950 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21953 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21954 noexcept(noexcept(JSONSerializer<Array>::from_json(
21955 std::declval<const basic_json_t&>(), v)))
21956 {
21957 JSONSerializer<Array>::from_json(*this, v);
21958 return v;
21959 }
21960
21963 template<typename ReferenceType, typename std::enable_if<
21964 std::is_reference<ReferenceType>::value, int>::type = 0>
21965 ReferenceType get_ref()
21966 {
21967 // delegate call to get_ref_impl
21968 return get_ref_impl<ReferenceType>(*this);
21969 }
21970
21973 template < typename ReferenceType, typename std::enable_if <
21974 std::is_reference<ReferenceType>::value&&
21975 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21976 ReferenceType get_ref() const
21977 {
21978 // delegate call to get_ref_impl
21979 return get_ref_impl<ReferenceType>(*this);
21980 }
21981
22011 template < typename ValueType, typename std::enable_if <
22019#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
22021#endif
22022#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
22024#endif
22026 >::value, int >::type = 0 >
22027 JSON_EXPLICIT operator ValueType() const
22028 {
22029 // delegate the call to get<>() const
22030 return get<ValueType>();
22031 }
22032
22036 {
22037 if (!is_binary())
22038 {
22039 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22040 }
22041
22042 return *get_ptr<binary_t*>();
22043 }
22044
22047 const binary_t& get_binary() const
22048 {
22049 if (!is_binary())
22050 {
22051 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22052 }
22053
22054 return *get_ptr<const binary_t*>();
22055 }
22056
22058
22060 // element access //
22062
22066
22070 {
22071 // at only works for arrays
22073 {
22074 JSON_TRY
22075 {
22076 return set_parent(m_data.m_value.array->at(idx));
22077 }
22078 JSON_CATCH (std::out_of_range&)
22079 {
22080 // create a better exception explanation
22081 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22082 } // cppcheck-suppress[missingReturn]
22083 }
22084 else
22085 {
22086 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22087 }
22088 }
22089
22093 {
22094 // at only works for arrays
22096 {
22097 JSON_TRY
22098 {
22099 return m_data.m_value.array->at(idx);
22100 }
22101 JSON_CATCH (std::out_of_range&)
22102 {
22103 // create a better exception explanation
22104 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22105 } // cppcheck-suppress[missingReturn]
22106 }
22107 else
22108 {
22109 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22110 }
22111 }
22112
22115 reference at(const typename object_t::key_type& key)
22116 {
22117 // at only works for objects
22119 {
22120 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22121 }
22122
22123 auto it = m_data.m_value.object->find(key);
22124 if (it == m_data.m_value.object->end())
22125 {
22126 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22127 }
22128 return set_parent(it->second);
22129 }
22130
22133 template<class KeyType, detail::enable_if_t<
22135 reference at(KeyType && key)
22136 {
22137 // at only works for objects
22139 {
22140 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22141 }
22142
22143 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22144 if (it == m_data.m_value.object->end())
22145 {
22146 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22147 }
22148 return set_parent(it->second);
22149 }
22150
22153 const_reference at(const typename object_t::key_type& key) const
22154 {
22155 // at only works for objects
22157 {
22158 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22159 }
22160
22161 auto it = m_data.m_value.object->find(key);
22162 if (it == m_data.m_value.object->end())
22163 {
22164 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22165 }
22166 return it->second;
22167 }
22168
22171 template<class KeyType, detail::enable_if_t<
22173 const_reference at(KeyType && key) const
22174 {
22175 // at only works for objects
22177 {
22178 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22179 }
22180
22181 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22182 if (it == m_data.m_value.object->end())
22183 {
22184 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22185 }
22186 return it->second;
22187 }
22188
22192 {
22193 // implicitly convert a null value to an empty array
22194 if (is_null())
22195 {
22196 m_data.m_type = value_t::array;
22197 m_data.m_value.array = create<array_t>();
22198 assert_invariant();
22199 }
22200
22201 // operator[] only works for arrays
22203 {
22204 // fill up the array with null values if given idx is outside the range
22205 if (idx >= m_data.m_value.array->size())
22206 {
22207#if JSON_DIAGNOSTICS
22208 // remember array size & capacity before resizing
22209 const auto old_size = m_data.m_value.array->size();
22210 const auto old_capacity = m_data.m_value.array->capacity();
22211#endif
22212 m_data.m_value.array->resize(idx + 1);
22213
22214#if JSON_DIAGNOSTICS
22215 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
22216 {
22217 // capacity has changed: update all parents
22218 set_parents();
22219 }
22220 else
22221 {
22222 // set parent for values added above
22223 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
22224 }
22225#endif
22226 assert_invariant();
22227 }
22228
22229 return m_data.m_value.array->operator[](idx);
22230 }
22231
22232 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22233 }
22234
22238 {
22239 // const operator[] only works for arrays
22241 {
22242 return m_data.m_value.array->operator[](idx);
22243 }
22244
22245 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22246 }
22247
22250 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
22251 {
22252 // implicitly convert a null value to an empty object
22253 if (is_null())
22254 {
22255 m_data.m_type = value_t::object;
22256 m_data.m_value.object = create<object_t>();
22257 assert_invariant();
22258 }
22259
22260 // operator[] only works for objects
22262 {
22263 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
22264 return set_parent(result.first->second);
22265 }
22266
22267 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22268 }
22269
22272 const_reference operator[](const typename object_t::key_type& key) const
22273 {
22274 // const operator[] only works for objects
22276 {
22277 auto it = m_data.m_value.object->find(key);
22278 JSON_ASSERT(it != m_data.m_value.object->end());
22279 return it->second;
22280 }
22281
22282 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22283 }
22284
22285 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
22286 // (they seemingly cannot be constrained to resolve the ambiguity)
22287 template<typename T>
22289 {
22290 return operator[](typename object_t::key_type(key));
22291 }
22292
22293 template<typename T>
22295 {
22296 return operator[](typename object_t::key_type(key));
22297 }
22298
22301 template<class KeyType, detail::enable_if_t<
22304 {
22305 // implicitly convert a null value to an empty object
22306 if (is_null())
22307 {
22308 m_data.m_type = value_t::object;
22309 m_data.m_value.object = create<object_t>();
22310 assert_invariant();
22311 }
22312
22313 // operator[] only works for objects
22315 {
22316 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
22317 return set_parent(result.first->second);
22318 }
22319
22320 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22321 }
22322
22325 template<class KeyType, detail::enable_if_t<
22328 {
22329 // const operator[] only works for objects
22331 {
22332 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22333 JSON_ASSERT(it != m_data.m_value.object->end());
22334 return it->second;
22335 }
22336
22337 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22338 }
22339
22340 private:
22341 template<typename KeyType>
22342 using is_comparable_with_object_key = detail::is_comparable <
22343 object_comparator_t, const typename object_t::key_type&, KeyType >;
22344
22345 template<typename ValueType>
22346 using value_return_type = std::conditional <
22348 string_t, typename std::decay<ValueType>::type >;
22349
22350 public:
22353 template < class ValueType, detail::enable_if_t <
22356 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22357 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
22358 {
22359 // value only works for objects
22361 {
22362 // If 'key' is found, return its value. Otherwise, return `default_value'.
22363 const auto it = find(key);
22364 if (it != end())
22365 {
22366 return it->template get<ValueType>();
22367 }
22368
22369 return default_value;
22370 }
22371
22372 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22373 }
22374
22377 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22381 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22382 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
22383 {
22384 // value only works for objects
22386 {
22387 // If 'key' is found, return its value. Otherwise, return `default_value'.
22388 const auto it = find(key);
22389 if (it != end())
22390 {
22391 return it->template get<ReturnType>();
22392 }
22393
22394 return std::forward<ValueType>(default_value);
22395 }
22396
22397 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22398 }
22399
22402 template < class ValueType, class KeyType, detail::enable_if_t <
22405 && is_comparable_with_object_key<KeyType>::value
22407 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22408 ValueType value(KeyType && key, const ValueType& default_value) const
22409 {
22410 // value only works for objects
22412 {
22413 // If 'key' is found, return its value. Otherwise, return `default_value'.
22414 const auto it = find(std::forward<KeyType>(key));
22415 if (it != end())
22416 {
22417 return it->template get<ValueType>();
22418 }
22419
22420 return default_value;
22421 }
22422
22423 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22424 }
22425
22428 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
22432 && is_comparable_with_object_key<KeyType>::value
22434 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22435 ReturnType value(KeyType && key, ValueType && default_value) const
22436 {
22437 // value only works for objects
22439 {
22440 // If 'key' is found, return its value. Otherwise, return `default_value'.
22441 const auto it = find(std::forward<KeyType>(key));
22442 if (it != end())
22443 {
22444 return it->template get<ReturnType>();
22445 }
22446
22447 return std::forward<ValueType>(default_value);
22448 }
22449
22450 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22451 }
22452
22455 template < class ValueType, detail::enable_if_t <
22457 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22458 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
22459 {
22460 // value only works for objects
22462 {
22463 // If the pointer resolves to a value, return it. Otherwise, return
22464 // 'default_value'.
22465 JSON_TRY
22466 {
22467 return ptr.get_checked(this).template get<ValueType>();
22468 }
22470 {
22471 return default_value;
22472 }
22473 }
22474
22475 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22476 }
22477
22480 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22483 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22484 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
22485 {
22486 // value only works for objects
22488 {
22489 // If the pointer resolves to a value, return it. Otherwise, return
22490 // 'default_value'.
22491 JSON_TRY
22492 {
22493 return ptr.get_checked(this).template get<ReturnType>();
22494 }
22496 {
22497 return std::forward<ValueType>(default_value);
22498 }
22499 }
22500
22501 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22502 }
22503
22504 template < class ValueType, class BasicJsonType, detail::enable_if_t <
22507 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22508 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22509 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
22510 {
22511 return value(ptr.convert(), default_value);
22512 }
22513
22514 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
22518 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22519 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22520 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
22521 {
22522 return value(ptr.convert(), std::forward<ValueType>(default_value));
22523 }
22524
22528 {
22529 return *begin();
22530 }
22531
22535 {
22536 return *cbegin();
22537 }
22538
22542 {
22543 auto tmp = end();
22544 --tmp;
22545 return *tmp;
22546 }
22547
22551 {
22552 auto tmp = cend();
22553 --tmp;
22554 return *tmp;
22555 }
22556
22559 template < class IteratorType, detail::enable_if_t <
22560 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22561 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22562 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
22563 {
22564 // make sure the iterator fits the current value
22565 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
22566 {
22567 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22568 }
22569
22570 IteratorType result = end();
22571
22572 switch (m_data.m_type)
22573 {
22574 case value_t::boolean:
22575 case value_t::number_float:
22576 case value_t::number_integer:
22577 case value_t::number_unsigned:
22578 case value_t::string:
22579 case value_t::binary:
22580 {
22581 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
22582 {
22583 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
22584 }
22585
22586 if (is_string())
22587 {
22588 AllocatorType<string_t> alloc;
22589 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22590 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22591 m_data.m_value.string = nullptr;
22592 }
22593 else if (is_binary())
22594 {
22595 AllocatorType<binary_t> alloc;
22596 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22597 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22598 m_data.m_value.binary = nullptr;
22599 }
22600
22601 m_data.m_type = value_t::null;
22602 assert_invariant();
22603 break;
22604 }
22605
22606 case value_t::object:
22607 {
22608 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
22609 break;
22610 }
22611
22612 case value_t::array:
22613 {
22614 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
22615 break;
22616 }
22617
22618 case value_t::null:
22619 case value_t::discarded:
22620 default:
22621 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22622 }
22623
22624 return result;
22625 }
22626
22629 template < class IteratorType, detail::enable_if_t <
22630 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22631 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22632 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
22633 {
22634 // make sure the iterator fits the current value
22635 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22636 {
22637 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22638 }
22639
22640 IteratorType result = end();
22641
22642 switch (m_data.m_type)
22643 {
22644 case value_t::boolean:
22645 case value_t::number_float:
22646 case value_t::number_integer:
22647 case value_t::number_unsigned:
22648 case value_t::string:
22649 case value_t::binary:
22650 {
22651 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22652 || !last.m_it.primitive_iterator.is_end()))
22653 {
22654 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22655 }
22656
22657 if (is_string())
22658 {
22659 AllocatorType<string_t> alloc;
22660 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22661 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22662 m_data.m_value.string = nullptr;
22663 }
22664 else if (is_binary())
22665 {
22666 AllocatorType<binary_t> alloc;
22667 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22668 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22669 m_data.m_value.binary = nullptr;
22670 }
22671
22672 m_data.m_type = value_t::null;
22673 assert_invariant();
22674 break;
22675 }
22676
22677 case value_t::object:
22678 {
22679 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22680 last.m_it.object_iterator);
22681 break;
22682 }
22683
22684 case value_t::array:
22685 {
22686 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22687 last.m_it.array_iterator);
22688 break;
22689 }
22690
22691 case value_t::null:
22692 case value_t::discarded:
22693 default:
22694 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22695 }
22696
22697 return result;
22698 }
22699
22700 private:
22701 template < typename KeyType, detail::enable_if_t <
22703 size_type erase_internal(KeyType && key)
22704 {
22705 // this erase only works for objects
22706 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22707 {
22708 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22709 }
22710
22711 return m_data.m_value.object->erase(std::forward<KeyType>(key));
22712 }
22713
22714 template < typename KeyType, detail::enable_if_t <
22715 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22716 size_type erase_internal(KeyType && key)
22717 {
22718 // this erase only works for objects
22719 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22720 {
22721 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22722 }
22723
22724 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22725 if (it != m_data.m_value.object->end())
22726 {
22727 m_data.m_value.object->erase(it);
22728 return 1;
22729 }
22730 return 0;
22731 }
22732
22733 public:
22734
22737 size_type erase(const typename object_t::key_type& key)
22738 {
22739 // the indirection via erase_internal() is added to avoid making this
22740 // function a template and thus de-rank it during overload resolution
22741 return erase_internal(key);
22742 }
22743
22746 template<class KeyType, detail::enable_if_t<
22748 size_type erase(KeyType && key)
22749 {
22750 return erase_internal(std::forward<KeyType>(key));
22751 }
22752
22755 void erase(const size_type idx)
22756 {
22757 // this erase only works for arrays
22759 {
22760 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22761 {
22762 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22763 }
22764
22765 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22766 }
22767 else
22768 {
22769 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22770 }
22771 }
22772
22774
22776 // lookup //
22778
22781
22784 iterator find(const typename object_t::key_type& key)
22785 {
22786 auto result = end();
22787
22788 if (is_object())
22789 {
22790 result.m_it.object_iterator = m_data.m_value.object->find(key);
22791 }
22792
22793 return result;
22794 }
22795
22798 const_iterator find(const typename object_t::key_type& key) const
22799 {
22800 auto result = cend();
22801
22802 if (is_object())
22803 {
22804 result.m_it.object_iterator = m_data.m_value.object->find(key);
22805 }
22806
22807 return result;
22808 }
22809
22812 template<class KeyType, detail::enable_if_t<
22814 iterator find(KeyType && key)
22815 {
22816 auto result = end();
22817
22818 if (is_object())
22819 {
22820 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22821 }
22822
22823 return result;
22824 }
22825
22828 template<class KeyType, detail::enable_if_t<
22830 const_iterator find(KeyType && key) const
22831 {
22832 auto result = cend();
22833
22834 if (is_object())
22835 {
22836 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22837 }
22838
22839 return result;
22840 }
22841
22844 size_type count(const typename object_t::key_type& key) const
22845 {
22846 // return 0 for all nonobject types
22847 return is_object() ? m_data.m_value.object->count(key) : 0;
22848 }
22849
22852 template<class KeyType, detail::enable_if_t<
22854 size_type count(KeyType && key) const
22855 {
22856 // return 0 for all nonobject types
22857 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22858 }
22859
22862 bool contains(const typename object_t::key_type& key) const
22863 {
22864 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22865 }
22866
22869 template<class KeyType, detail::enable_if_t<
22871 bool contains(KeyType && key) const
22872 {
22873 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22874 }
22875
22878 bool contains(const json_pointer& ptr) const
22879 {
22880 return ptr.contains(this);
22881 }
22882
22883 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22884 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22885 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22886 {
22887 return ptr.contains(this);
22888 }
22889
22891
22893 // iterators //
22895
22898
22901 iterator begin() noexcept
22902 {
22903 iterator result(this);
22904 result.set_begin();
22905 return result;
22906 }
22907
22910 const_iterator begin() const noexcept
22911 {
22912 return cbegin();
22913 }
22914
22917 const_iterator cbegin() const noexcept
22918 {
22919 const_iterator result(this);
22920 result.set_begin();
22921 return result;
22922 }
22923
22926 iterator end() noexcept
22927 {
22928 iterator result(this);
22929 result.set_end();
22930 return result;
22931 }
22932
22935 const_iterator end() const noexcept
22936 {
22937 return cend();
22938 }
22939
22942 const_iterator cend() const noexcept
22943 {
22944 const_iterator result(this);
22945 result.set_end();
22946 return result;
22947 }
22948
22952 {
22953 return reverse_iterator(end());
22954 }
22955
22959 {
22960 return crbegin();
22961 }
22962
22966 {
22967 return reverse_iterator(begin());
22968 }
22969
22973 {
22974 return crend();
22975 }
22976
22980 {
22981 return const_reverse_iterator(cend());
22982 }
22983
22987 {
22989 }
22990
22991 public:
22997 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22998 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22999 {
23000 return ref.items();
23001 }
23002
23008 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
23009 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
23010 {
23011 return ref.items();
23012 }
23013
23016 iteration_proxy<iterator> items() noexcept
23017 {
23018 return iteration_proxy<iterator>(*this);
23019 }
23020
23023 iteration_proxy<const_iterator> items() const noexcept
23024 {
23025 return iteration_proxy<const_iterator>(*this);
23026 }
23027
23029
23031 // capacity //
23033
23036
23039 bool empty() const noexcept
23040 {
23041 switch (m_data.m_type)
23042 {
23043 case value_t::null:
23044 {
23045 // null values are empty
23046 return true;
23047 }
23048
23049 case value_t::array:
23050 {
23051 // delegate call to array_t::empty()
23052 return m_data.m_value.array->empty();
23053 }
23054
23055 case value_t::object:
23056 {
23057 // delegate call to object_t::empty()
23058 return m_data.m_value.object->empty();
23059 }
23060
23061 case value_t::string:
23062 case value_t::boolean:
23063 case value_t::number_integer:
23064 case value_t::number_unsigned:
23065 case value_t::number_float:
23066 case value_t::binary:
23067 case value_t::discarded:
23068 default:
23069 {
23070 // all other types are nonempty
23071 return false;
23072 }
23073 }
23074 }
23075
23078 size_type size() const noexcept
23079 {
23080 switch (m_data.m_type)
23081 {
23082 case value_t::null:
23083 {
23084 // null values are empty
23085 return 0;
23086 }
23087
23088 case value_t::array:
23089 {
23090 // delegate call to array_t::size()
23091 return m_data.m_value.array->size();
23092 }
23093
23094 case value_t::object:
23095 {
23096 // delegate call to object_t::size()
23097 return m_data.m_value.object->size();
23098 }
23099
23100 case value_t::string:
23101 case value_t::boolean:
23102 case value_t::number_integer:
23103 case value_t::number_unsigned:
23104 case value_t::number_float:
23105 case value_t::binary:
23106 case value_t::discarded:
23107 default:
23108 {
23109 // all other types have size 1
23110 return 1;
23111 }
23112 }
23113 }
23114
23117 size_type max_size() const noexcept
23118 {
23119 switch (m_data.m_type)
23120 {
23121 case value_t::array:
23122 {
23123 // delegate call to array_t::max_size()
23124 return m_data.m_value.array->max_size();
23125 }
23126
23127 case value_t::object:
23128 {
23129 // delegate call to object_t::max_size()
23130 return m_data.m_value.object->max_size();
23131 }
23132
23133 case value_t::null:
23134 case value_t::string:
23135 case value_t::boolean:
23136 case value_t::number_integer:
23137 case value_t::number_unsigned:
23138 case value_t::number_float:
23139 case value_t::binary:
23140 case value_t::discarded:
23141 default:
23142 {
23143 // all other types have max_size() == size()
23144 return size();
23145 }
23146 }
23147 }
23148
23150
23152 // modifiers //
23154
23157
23160 void clear() noexcept
23161 {
23162 switch (m_data.m_type)
23163 {
23164 case value_t::number_integer:
23165 {
23166 m_data.m_value.number_integer = 0;
23167 break;
23168 }
23169
23170 case value_t::number_unsigned:
23171 {
23172 m_data.m_value.number_unsigned = 0;
23173 break;
23174 }
23175
23176 case value_t::number_float:
23177 {
23178 m_data.m_value.number_float = 0.0;
23179 break;
23180 }
23181
23182 case value_t::boolean:
23183 {
23184 m_data.m_value.boolean = false;
23185 break;
23186 }
23187
23188 case value_t::string:
23189 {
23190 m_data.m_value.string->clear();
23191 break;
23192 }
23193
23194 case value_t::binary:
23195 {
23196 m_data.m_value.binary->clear();
23197 break;
23198 }
23199
23200 case value_t::array:
23201 {
23202 m_data.m_value.array->clear();
23203 break;
23204 }
23205
23206 case value_t::object:
23207 {
23208 m_data.m_value.object->clear();
23209 break;
23210 }
23211
23212 case value_t::null:
23213 case value_t::discarded:
23214 default:
23215 break;
23216 }
23217 }
23218
23222 {
23223 // push_back only works for null objects or arrays
23224 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23225 {
23226 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23227 }
23228
23229 // transform a null object into an array
23230 if (is_null())
23231 {
23232 m_data.m_type = value_t::array;
23233 m_data.m_value = value_t::array;
23234 assert_invariant();
23235 }
23236
23237 // add the element to the array (move semantics)
23238 const auto old_capacity = m_data.m_value.array->capacity();
23239 m_data.m_value.array->push_back(std::move(val));
23240 set_parent(m_data.m_value.array->back(), old_capacity);
23241 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
23242 }
23243
23247 {
23248 push_back(std::move(val));
23249 return *this;
23250 }
23251
23254 void push_back(const basic_json& val)
23255 {
23256 // push_back only works for null objects or arrays
23257 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23258 {
23259 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23260 }
23261
23262 // transform a null object into an array
23263 if (is_null())
23264 {
23265 m_data.m_type = value_t::array;
23266 m_data.m_value = value_t::array;
23267 assert_invariant();
23268 }
23269
23270 // add the element to the array
23271 const auto old_capacity = m_data.m_value.array->capacity();
23272 m_data.m_value.array->push_back(val);
23273 set_parent(m_data.m_value.array->back(), old_capacity);
23274 }
23275
23279 {
23280 push_back(val);
23281 return *this;
23282 }
23283
23286 void push_back(const typename object_t::value_type& val)
23287 {
23288 // push_back only works for null objects or objects
23289 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23290 {
23291 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23292 }
23293
23294 // transform a null object into an object
23295 if (is_null())
23296 {
23297 m_data.m_type = value_t::object;
23298 m_data.m_value = value_t::object;
23299 assert_invariant();
23300 }
23301
23302 // add the element to the object
23303 auto res = m_data.m_value.object->insert(val);
23304 set_parent(res.first->second);
23305 }
23306
23309 reference operator+=(const typename object_t::value_type& val)
23310 {
23311 push_back(val);
23312 return *this;
23313 }
23314
23318 {
23319 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
23320 {
23321 basic_json&& key = init.begin()->moved_or_copied();
23322 push_back(typename object_t::value_type(
23323 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
23324 }
23325 else
23326 {
23327 push_back(basic_json(init));
23328 }
23329 }
23330
23334 {
23335 push_back(init);
23336 return *this;
23337 }
23338
23341 template<class... Args>
23342 reference emplace_back(Args&& ... args)
23343 {
23344 // emplace_back only works for null objects or arrays
23345 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23346 {
23347 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
23348 }
23349
23350 // transform a null object into an array
23351 if (is_null())
23352 {
23353 m_data.m_type = value_t::array;
23354 m_data.m_value = value_t::array;
23355 assert_invariant();
23356 }
23357
23358 // add the element to the array (perfect forwarding)
23359 const auto old_capacity = m_data.m_value.array->capacity();
23360 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
23361 return set_parent(m_data.m_value.array->back(), old_capacity);
23362 }
23363
23366 template<class... Args>
23367 std::pair<iterator, bool> emplace(Args&& ... args)
23368 {
23369 // emplace only works for null objects or arrays
23370 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23371 {
23372 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
23373 }
23374
23375 // transform a null object into an object
23376 if (is_null())
23377 {
23378 m_data.m_type = value_t::object;
23379 m_data.m_value = value_t::object;
23380 assert_invariant();
23381 }
23382
23383 // add the element to the array (perfect forwarding)
23384 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
23385 set_parent(res.first->second);
23386
23387 // create a result iterator and set iterator to the result of emplace
23388 auto it = begin();
23389 it.m_it.object_iterator = res.first;
23390
23391 // return pair of iterator and boolean
23392 return {it, res.second};
23393 }
23394
23398 template<typename... Args>
23399 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
23400 {
23401 iterator result(this);
23402 JSON_ASSERT(m_data.m_value.array != nullptr);
23403
23404 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
23405 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
23406 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
23407
23408 // This could have been written as:
23409 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
23410 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
23411
23412 set_parents();
23413 return result;
23414 }
23415
23418 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23419 {
23420 // insert only works for arrays
23422 {
23423 // check if iterator pos fits to this JSON value
23424 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23425 {
23426 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23427 }
23428
23429 // insert to array and return iterator
23430 return insert_iterator(pos, val);
23431 }
23432
23433 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23434 }
23435
23438 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
23439 {
23440 return insert(pos, val);
23441 }
23442
23445 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23446 {
23447 // insert only works for arrays
23449 {
23450 // check if iterator pos fits to this JSON value
23451 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23452 {
23453 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23454 }
23455
23456 // insert to array and return iterator
23457 return insert_iterator(pos, cnt, val);
23458 }
23459
23460 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23461 }
23462
23465 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23466 {
23467 // insert only works for arrays
23469 {
23470 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23471 }
23472
23473 // check if iterator pos fits to this JSON value
23474 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23475 {
23476 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23477 }
23478
23479 // check if range iterators belong to the same JSON object
23480 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23481 {
23482 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23483 }
23484
23485 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
23486 {
23487 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
23488 }
23489
23490 // insert to array and return iterator
23491 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
23492 }
23493
23496 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
23497 {
23498 // insert only works for arrays
23500 {
23501 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23502 }
23503
23504 // check if iterator pos fits to this JSON value
23505 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23506 {
23507 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23508 }
23509
23510 // insert to array and return iterator
23511 return insert_iterator(pos, ilist.begin(), ilist.end());
23512 }
23513
23516 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23517 {
23518 // insert only works for objects
23520 {
23521 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23522 }
23523
23524 // check if range iterators belong to the same JSON object
23525 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23526 {
23527 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23528 }
23529
23530 // passed iterators must belong to objects
23531 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23532 {
23533 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
23534 }
23535
23536 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
23537 set_parents();
23538 }
23539
23542 void update(const_reference j, bool merge_objects = false)
23543 {
23544 update(j.begin(), j.end(), merge_objects);
23545 }
23546
23549 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
23550 {
23551 // implicitly convert a null value to an empty object
23552 if (is_null())
23553 {
23554 m_data.m_type = value_t::object;
23555 m_data.m_value.object = create<object_t>();
23556 assert_invariant();
23557 }
23558
23560 {
23561 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
23562 }
23563
23564 // check if range iterators belong to the same JSON object
23565 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23566 {
23567 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23568 }
23569
23570 // passed iterators must belong to objects
23571 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23572 {
23573 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
23574 }
23575
23576 for (auto it = first; it != last; ++it)
23577 {
23578 if (merge_objects && it.value().is_object())
23579 {
23580 auto it2 = m_data.m_value.object->find(it.key());
23581 if (it2 != m_data.m_value.object->end())
23582 {
23583 it2->second.update(it.value(), true);
23584 continue;
23585 }
23586 }
23587 m_data.m_value.object->operator[](it.key()) = it.value();
23588#if JSON_DIAGNOSTICS
23589 m_data.m_value.object->operator[](it.key()).m_parent = this;
23590#endif
23591 }
23592 }
23593
23596 void swap(reference other) noexcept (
23597 std::is_nothrow_move_constructible<value_t>::value&&
23598 std::is_nothrow_move_assignable<value_t>::value&&
23599 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23600 std::is_nothrow_move_assignable<json_value>::value
23601 )
23602 {
23603 std::swap(m_data.m_type, other.m_data.m_type);
23604 std::swap(m_data.m_value, other.m_data.m_value);
23605
23606 set_parents();
23607 other.set_parents();
23608 assert_invariant();
23609 }
23610
23613 friend void swap(reference left, reference right) noexcept (
23614 std::is_nothrow_move_constructible<value_t>::value&&
23615 std::is_nothrow_move_assignable<value_t>::value&&
23616 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23617 std::is_nothrow_move_assignable<json_value>::value
23618 )
23619 {
23620 left.swap(right);
23621 }
23622
23625 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23626 {
23627 // swap only works for arrays
23629 {
23630 using std::swap;
23631 swap(*(m_data.m_value.array), other);
23632 }
23633 else
23634 {
23635 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23636 }
23637 }
23638
23641 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23642 {
23643 // swap only works for objects
23645 {
23646 using std::swap;
23647 swap(*(m_data.m_value.object), other);
23648 }
23649 else
23650 {
23651 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23652 }
23653 }
23654
23657 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23658 {
23659 // swap only works for strings
23661 {
23662 using std::swap;
23663 swap(*(m_data.m_value.string), other);
23664 }
23665 else
23666 {
23667 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23668 }
23669 }
23670
23673 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23674 {
23675 // swap only works for strings
23677 {
23678 using std::swap;
23679 swap(*(m_data.m_value.binary), other);
23680 }
23681 else
23682 {
23683 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23684 }
23685 }
23686
23689 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23690 {
23691 // swap only works for strings
23693 {
23694 using std::swap;
23695 swap(*(m_data.m_value.binary), other);
23696 }
23697 else
23698 {
23699 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23700 }
23701 }
23702
23704
23706 // lexicographical comparison operators //
23708
23711
23712 // note parentheses around operands are necessary; see
23713 // https://github.com/nlohmann/json/issues/1530
23714#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
23715 const auto lhs_type = lhs.type(); \
23716 const auto rhs_type = rhs.type(); \
23717 \
23718 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
23719 { \
23720 switch (lhs_type) \
23721 { \
23722 case value_t::array: \
23723 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
23724 \
23725 case value_t::object: \
23726 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
23727 \
23728 case value_t::null: \
23729 return (null_result); \
23730 \
23731 case value_t::string: \
23732 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
23733 \
23734 case value_t::boolean: \
23735 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
23736 \
23737 case value_t::number_integer: \
23738 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
23739 \
23740 case value_t::number_unsigned: \
23741 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
23742 \
23743 case value_t::number_float: \
23744 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
23745 \
23746 case value_t::binary: \
23747 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
23748 \
23749 case value_t::discarded: \
23750 default: \
23751 return (unordered_result); \
23752 } \
23753 } \
23754 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
23755 { \
23756 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
23757 } \
23758 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
23759 { \
23760 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
23761 } \
23762 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
23763 { \
23764 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
23765 } \
23766 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
23767 { \
23768 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
23769 } \
23770 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
23771 { \
23772 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23773 } \
23774 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
23775 { \
23776 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23777 } \
23778 else if(compares_unordered(lhs, rhs))\
23779 {\
23780 return (unordered_result);\
23781 }\
23782 \
23783 return (default_result);
23784
23786 // returns true if:
23787 // - any operand is NaN and the other operand is of number type
23788 // - any operand is discarded
23789 // in legacy mode, discarded values are considered ordered if
23790 // an operation is computed as an odd number of inverses of others
23791 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23792 {
23793 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23794 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23795 {
23796 return true;
23797 }
23798#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23799 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23800#else
23801 static_cast<void>(inverse);
23802 return lhs.is_discarded() || rhs.is_discarded();
23803#endif
23804 }
23805
23806 private:
23807 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23808 {
23809 return compares_unordered(*this, rhs, inverse);
23810 }
23811
23812 public:
23813#if JSON_HAS_THREE_WAY_COMPARISON
23816 bool operator==(const_reference rhs) const noexcept
23817 {
23818#ifdef __GNUC__
23819#pragma GCC diagnostic push
23820#pragma GCC diagnostic ignored "-Wfloat-equal"
23821#endif
23822 const_reference lhs = *this;
23823 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23824#ifdef __GNUC__
23825#pragma GCC diagnostic pop
23826#endif
23827 }
23828
23831 template<typename ScalarType>
23832 requires std::is_scalar_v<ScalarType>
23833 bool operator==(ScalarType rhs) const noexcept
23834 {
23835 return *this == basic_json(rhs);
23836 }
23837
23840 bool operator!=(const_reference rhs) const noexcept
23841 {
23842 if (compares_unordered(rhs, true))
23843 {
23844 return false;
23845 }
23846 return !operator==(rhs);
23847 }
23848
23851 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23852 {
23853 const_reference lhs = *this;
23854 // default_result is used if we cannot compare values. In that case,
23855 // we compare types.
23856 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23857 std::partial_ordering::equivalent,
23858 std::partial_ordering::unordered,
23859 lhs_type <=> rhs_type) // *NOPAD*
23860 }
23861
23864 template<typename ScalarType>
23865 requires std::is_scalar_v<ScalarType>
23866 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23867 {
23868 return *this <=> basic_json(rhs); // *NOPAD*
23869 }
23870
23871#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23872 // all operators that are computed as an odd number of inverses of others
23873 // need to be overloaded to emulate the legacy comparison behavior
23874
23878 bool operator<=(const_reference rhs) const noexcept
23879 {
23880 if (compares_unordered(rhs, true))
23881 {
23882 return false;
23883 }
23884 return !(rhs < *this);
23885 }
23886
23889 template<typename ScalarType>
23890 requires std::is_scalar_v<ScalarType>
23891 bool operator<=(ScalarType rhs) const noexcept
23892 {
23893 return *this <= basic_json(rhs);
23894 }
23895
23899 bool operator>=(const_reference rhs) const noexcept
23900 {
23901 if (compares_unordered(rhs, true))
23902 {
23903 return false;
23904 }
23905 return !(*this < rhs);
23906 }
23907
23910 template<typename ScalarType>
23911 requires std::is_scalar_v<ScalarType>
23912 bool operator>=(ScalarType rhs) const noexcept
23913 {
23914 return *this >= basic_json(rhs);
23915 }
23916#endif
23917#else
23920 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23921 {
23922#ifdef __GNUC__
23923#pragma GCC diagnostic push
23924#pragma GCC diagnostic ignored "-Wfloat-equal"
23925#endif
23926 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23927#ifdef __GNUC__
23928#pragma GCC diagnostic pop
23929#endif
23930 }
23931
23934 template<typename ScalarType, typename std::enable_if<
23935 std::is_scalar<ScalarType>::value, int>::type = 0>
23936 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23937 {
23938 return lhs == basic_json(rhs);
23939 }
23940
23943 template<typename ScalarType, typename std::enable_if<
23944 std::is_scalar<ScalarType>::value, int>::type = 0>
23945 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23946 {
23947 return basic_json(lhs) == rhs;
23948 }
23949
23952 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23953 {
23954 if (compares_unordered(lhs, rhs, true))
23955 {
23956 return false;
23957 }
23958 return !(lhs == rhs);
23959 }
23960
23963 template<typename ScalarType, typename std::enable_if<
23964 std::is_scalar<ScalarType>::value, int>::type = 0>
23965 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23966 {
23967 return lhs != basic_json(rhs);
23968 }
23969
23972 template<typename ScalarType, typename std::enable_if<
23973 std::is_scalar<ScalarType>::value, int>::type = 0>
23974 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23975 {
23976 return basic_json(lhs) != rhs;
23977 }
23978
23981 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23982 {
23983 // default_result is used if we cannot compare values. In that case,
23984 // we compare types. Note we have to call the operator explicitly,
23985 // because MSVC has problems otherwise.
23986 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23987 }
23988
23991 template<typename ScalarType, typename std::enable_if<
23992 std::is_scalar<ScalarType>::value, int>::type = 0>
23993 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23994 {
23995 return lhs < basic_json(rhs);
23996 }
23997
24000 template<typename ScalarType, typename std::enable_if<
24001 std::is_scalar<ScalarType>::value, int>::type = 0>
24002 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
24003 {
24004 return basic_json(lhs) < rhs;
24005 }
24006
24009 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
24010 {
24011 if (compares_unordered(lhs, rhs, true))
24012 {
24013 return false;
24014 }
24015 return !(rhs < lhs);
24016 }
24017
24020 template<typename ScalarType, typename std::enable_if<
24021 std::is_scalar<ScalarType>::value, int>::type = 0>
24022 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
24023 {
24024 return lhs <= basic_json(rhs);
24025 }
24026
24029 template<typename ScalarType, typename std::enable_if<
24030 std::is_scalar<ScalarType>::value, int>::type = 0>
24031 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
24032 {
24033 return basic_json(lhs) <= rhs;
24034 }
24035
24038 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
24039 {
24040 // double inverse
24041 if (compares_unordered(lhs, rhs))
24042 {
24043 return false;
24044 }
24045 return !(lhs <= rhs);
24046 }
24047
24050 template<typename ScalarType, typename std::enable_if<
24051 std::is_scalar<ScalarType>::value, int>::type = 0>
24052 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
24053 {
24054 return lhs > basic_json(rhs);
24055 }
24056
24059 template<typename ScalarType, typename std::enable_if<
24060 std::is_scalar<ScalarType>::value, int>::type = 0>
24061 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
24062 {
24063 return basic_json(lhs) > rhs;
24064 }
24065
24068 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
24069 {
24070 if (compares_unordered(lhs, rhs, true))
24071 {
24072 return false;
24073 }
24074 return !(lhs < rhs);
24075 }
24076
24079 template<typename ScalarType, typename std::enable_if<
24080 std::is_scalar<ScalarType>::value, int>::type = 0>
24081 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
24082 {
24083 return lhs >= basic_json(rhs);
24084 }
24085
24088 template<typename ScalarType, typename std::enable_if<
24089 std::is_scalar<ScalarType>::value, int>::type = 0>
24090 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
24091 {
24092 return basic_json(lhs) >= rhs;
24093 }
24094#endif
24095
24096#undef JSON_IMPLEMENT_OPERATOR
24097
24099
24101 // serialization //
24103
24106#ifndef JSON_NO_IO
24109 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
24110 {
24111 // read width member and use it as the indentation parameter if nonzero
24112 const bool pretty_print = o.width() > 0;
24113 const auto indentation = pretty_print ? o.width() : 0;
24114
24115 // reset width to 0 for subsequent calls to this stream
24116 o.width(0);
24117
24118 // do the actual serialization
24119 serializer s(detail::output_adapter<char>(o), o.fill());
24120 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
24121 return o;
24122 }
24123
24130 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
24131 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
24132 {
24133 return o << j;
24134 }
24135#endif // JSON_NO_IO
24137
24139 // deserialization //
24141
24144
24147 template<typename InputType>
24149 static basic_json parse(InputType&& i,
24150 parser_callback_t cb = nullptr,
24151 const bool allow_exceptions = true,
24152 const bool ignore_comments = false,
24153 const bool ignore_trailing_commas = false)
24154 {
24155 basic_json result;
24156 parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded]
24157 return result;
24158 }
24159
24162 template<typename IteratorType>
24164 static basic_json parse(IteratorType first,
24165 IteratorType last,
24166 parser_callback_t cb = nullptr,
24167 const bool allow_exceptions = true,
24168 const bool ignore_comments = false,
24169 const bool ignore_trailing_commas = false)
24170 {
24171 basic_json result;
24172 parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
24173 return result;
24174 }
24175
24177 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
24178 static basic_json parse(detail::span_input_adapter&& i,
24179 parser_callback_t cb = nullptr,
24180 const bool allow_exceptions = true,
24181 const bool ignore_comments = false,
24182 const bool ignore_trailing_commas = false)
24183 {
24184 basic_json result;
24185 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
24186 return result;
24187 }
24188
24191 template<typename InputType>
24192 static bool accept(InputType&& i,
24193 const bool ignore_comments = false,
24194 const bool ignore_trailing_commas = false)
24195 {
24196 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24197 }
24198
24201 template<typename IteratorType>
24202 static bool accept(IteratorType first, IteratorType last,
24203 const bool ignore_comments = false,
24204 const bool ignore_trailing_commas = false)
24205 {
24206 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24207 }
24208
24210 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
24211 static bool accept(detail::span_input_adapter&& i,
24212 const bool ignore_comments = false,
24213 const bool ignore_trailing_commas = false)
24214 {
24215 return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24216 }
24217
24220 template <typename InputType, typename SAX>
24222 static bool sax_parse(InputType&& i, SAX* sax,
24224 const bool strict = true,
24225 const bool ignore_comments = false,
24226 const bool ignore_trailing_commas = false)
24227 {
24228 auto ia = detail::input_adapter(std::forward<InputType>(i));
24229 return format == input_format_t::json
24230 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24231 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24232 }
24233
24236 template<class IteratorType, class SAX>
24238 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
24240 const bool strict = true,
24241 const bool ignore_comments = false,
24242 const bool ignore_trailing_commas = false)
24243 {
24244 auto ia = detail::input_adapter(std::move(first), std::move(last));
24245 return format == input_format_t::json
24246 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24247 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24248 }
24249
24255 template <typename SAX>
24256 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
24258 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
24260 const bool strict = true,
24261 const bool ignore_comments = false,
24262 const bool ignore_trailing_commas = false)
24263 {
24264 auto ia = i.get();
24265 return format == input_format_t::json
24266 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24267 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24268 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24269 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24270 }
24271#ifndef JSON_NO_IO
24278 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
24279 friend std::istream& operator<<(basic_json& j, std::istream& i)
24280 {
24281 return operator>>(i, j);
24282 }
24283
24286 friend std::istream& operator>>(std::istream& i, basic_json& j)
24287 {
24288 parser(detail::input_adapter(i)).parse(false, j);
24289 return i;
24290 }
24291#endif // JSON_NO_IO
24293
24295 // convenience functions //
24297
24301 const char* type_name() const noexcept
24302 {
24303 switch (m_data.m_type)
24304 {
24305 case value_t::null:
24306 return "null";
24307 case value_t::object:
24308 return "object";
24309 case value_t::array:
24310 return "array";
24311 case value_t::string:
24312 return "string";
24313 case value_t::boolean:
24314 return "boolean";
24315 case value_t::binary:
24316 return "binary";
24317 case value_t::discarded:
24318 return "discarded";
24319 case value_t::number_integer:
24320 case value_t::number_unsigned:
24321 case value_t::number_float:
24322 return "number";
24323 default:
24324 return "invalid";
24325 }
24326 }
24327
24330 // member variables //
24332
24333 struct data
24334 {
24336 value_t m_type = value_t::null;
24337
24339 json_value m_value = {};
24340
24341 data(const value_t v)
24342 : m_type(v), m_value(v)
24343 {
24344 }
24345
24346 data(size_type cnt, const basic_json& val)
24347 : m_type(value_t::array)
24348 {
24349 m_value.array = create<array_t>(cnt, val);
24350 }
24351
24352 data() noexcept = default;
24353 data(data&&) noexcept = default;
24354 data(const data&) noexcept = delete;
24355 data& operator=(data&&) noexcept = delete;
24356 data& operator=(const data&) noexcept = delete;
24357
24358 ~data() noexcept
24359 {
24360 m_value.destroy(m_type);
24361 }
24362 };
24363
24365
24366#if JSON_DIAGNOSTICS
24368 basic_json* m_parent = nullptr;
24369#endif
24370
24371#if JSON_DIAGNOSTIC_POSITIONS
24373 std::size_t start_position = std::string::npos;
24375 std::size_t end_position = std::string::npos;
24376 public:
24377 constexpr std::size_t start_pos() const noexcept
24378 {
24379 return start_position;
24380 }
24381
24382 constexpr std::size_t end_pos() const noexcept
24383 {
24384 return end_position;
24385 }
24386#endif
24387
24389 // binary serialization/deserialization //
24391
24394
24395 public:
24398 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
24399 {
24400 std::vector<std::uint8_t> result;
24401 to_cbor(j, result);
24402 return result;
24403 }
24404
24408 {
24409 binary_writer<std::uint8_t>(o).write_cbor(j);
24410 }
24411
24415 {
24416 binary_writer<char>(o).write_cbor(j);
24417 }
24418
24421 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
24422 {
24423 std::vector<std::uint8_t> result;
24424 to_msgpack(j, result);
24425 return result;
24426 }
24427
24431 {
24432 binary_writer<std::uint8_t>(o).write_msgpack(j);
24433 }
24434
24438 {
24439 binary_writer<char>(o).write_msgpack(j);
24440 }
24441
24444 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
24445 const bool use_size = false,
24446 const bool use_type = false)
24447 {
24448 std::vector<std::uint8_t> result;
24449 to_ubjson(j, result, use_size, use_type);
24450 return result;
24451 }
24452
24456 const bool use_size = false, const bool use_type = false)
24457 {
24458 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
24459 }
24460
24464 const bool use_size = false, const bool use_type = false)
24465 {
24466 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
24467 }
24468
24471 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
24472 const bool use_size = false,
24473 const bool use_type = false,
24474 const bjdata_version_t version = bjdata_version_t::draft2)
24475 {
24476 std::vector<std::uint8_t> result;
24477 to_bjdata(j, result, use_size, use_type, version);
24478 return result;
24479 }
24480
24484 const bool use_size = false, const bool use_type = false,
24485 const bjdata_version_t version = bjdata_version_t::draft2)
24486 {
24487 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
24488 }
24489
24493 const bool use_size = false, const bool use_type = false,
24494 const bjdata_version_t version = bjdata_version_t::draft2)
24495 {
24496 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
24497 }
24498
24501 static std::vector<std::uint8_t> to_bson(const basic_json& j)
24502 {
24503 std::vector<std::uint8_t> result;
24504 to_bson(j, result);
24505 return result;
24506 }
24507
24511 {
24512 binary_writer<std::uint8_t>(o).write_bson(j);
24513 }
24514
24518 {
24519 binary_writer<char>(o).write_bson(j);
24520 }
24521
24524 template<typename InputType>
24526 static basic_json from_cbor(InputType&& i,
24527 const bool strict = true,
24528 const bool allow_exceptions = true,
24529 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24530 {
24531 basic_json result;
24532 auto ia = detail::input_adapter(std::forward<InputType>(i));
24533 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24534 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24535 return res ? result : basic_json(value_t::discarded);
24536 }
24537
24540 template<typename IteratorType>
24542 static basic_json from_cbor(IteratorType first, IteratorType last,
24543 const bool strict = true,
24544 const bool allow_exceptions = true,
24545 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24546 {
24547 basic_json result;
24548 auto ia = detail::input_adapter(std::move(first), std::move(last));
24549 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24550 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24551 return res ? result : basic_json(value_t::discarded);
24552 }
24553
24554 template<typename T>
24556 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24557 static basic_json from_cbor(const T* ptr, std::size_t len,
24558 const bool strict = true,
24559 const bool allow_exceptions = true,
24560 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24561 {
24562 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
24563 }
24564
24566 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24567 static basic_json from_cbor(detail::span_input_adapter&& i,
24568 const bool strict = true,
24569 const bool allow_exceptions = true,
24570 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24571 {
24572 basic_json result;
24573 auto ia = i.get();
24574 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24575 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24576 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24577 return res ? result : basic_json(value_t::discarded);
24578 }
24579
24582 template<typename InputType>
24584 static basic_json from_msgpack(InputType&& i,
24585 const bool strict = true,
24586 const bool allow_exceptions = true)
24587 {
24588 basic_json result;
24589 auto ia = detail::input_adapter(std::forward<InputType>(i));
24590 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24591 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24592 return res ? result : basic_json(value_t::discarded);
24593 }
24594
24597 template<typename IteratorType>
24599 static basic_json from_msgpack(IteratorType first, IteratorType last,
24600 const bool strict = true,
24601 const bool allow_exceptions = true)
24602 {
24603 basic_json result;
24604 auto ia = detail::input_adapter(std::move(first), std::move(last));
24605 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24606 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24607 return res ? result : basic_json(value_t::discarded);
24608 }
24609
24610 template<typename T>
24612 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24613 static basic_json from_msgpack(const T* ptr, std::size_t len,
24614 const bool strict = true,
24615 const bool allow_exceptions = true)
24616 {
24617 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24618 }
24619
24621 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24622 static basic_json from_msgpack(detail::span_input_adapter&& i,
24623 const bool strict = true,
24624 const bool allow_exceptions = true)
24625 {
24626 basic_json result;
24627 auto ia = i.get();
24628 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24629 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24630 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24631 return res ? result : basic_json(value_t::discarded);
24632 }
24633
24636 template<typename InputType>
24638 static basic_json from_ubjson(InputType&& i,
24639 const bool strict = true,
24640 const bool allow_exceptions = true)
24641 {
24642 basic_json result;
24643 auto ia = detail::input_adapter(std::forward<InputType>(i));
24644 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24645 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24646 return res ? result : basic_json(value_t::discarded);
24647 }
24648
24651 template<typename IteratorType>
24653 static basic_json from_ubjson(IteratorType first, IteratorType last,
24654 const bool strict = true,
24655 const bool allow_exceptions = true)
24656 {
24657 basic_json result;
24658 auto ia = detail::input_adapter(std::move(first), std::move(last));
24659 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24660 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24661 return res ? result : basic_json(value_t::discarded);
24662 }
24663
24664 template<typename T>
24666 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24667 static basic_json from_ubjson(const T* ptr, std::size_t len,
24668 const bool strict = true,
24669 const bool allow_exceptions = true)
24670 {
24671 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24672 }
24673
24675 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24676 static basic_json from_ubjson(detail::span_input_adapter&& i,
24677 const bool strict = true,
24678 const bool allow_exceptions = true)
24679 {
24680 basic_json result;
24681 auto ia = i.get();
24682 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24683 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24684 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24685 return res ? result : basic_json(value_t::discarded);
24686 }
24687
24690 template<typename InputType>
24692 static basic_json from_bjdata(InputType&& i,
24693 const bool strict = true,
24694 const bool allow_exceptions = true)
24695 {
24696 basic_json result;
24697 auto ia = detail::input_adapter(std::forward<InputType>(i));
24698 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24699 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
24700 return res ? result : basic_json(value_t::discarded);
24701 }
24702
24705 template<typename IteratorType>
24707 static basic_json from_bjdata(IteratorType first, IteratorType last,
24708 const bool strict = true,
24709 const bool allow_exceptions = true)
24710 {
24711 basic_json result;
24712 auto ia = detail::input_adapter(std::move(first), std::move(last));
24713 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24714 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
24715 return res ? result : basic_json(value_t::discarded);
24716 }
24717
24720 template<typename InputType>
24722 static basic_json from_bson(InputType&& i,
24723 const bool strict = true,
24724 const bool allow_exceptions = true)
24725 {
24726 basic_json result;
24727 auto ia = detail::input_adapter(std::forward<InputType>(i));
24728 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24729 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24730 return res ? result : basic_json(value_t::discarded);
24731 }
24732
24735 template<typename IteratorType>
24737 static basic_json from_bson(IteratorType first, IteratorType last,
24738 const bool strict = true,
24739 const bool allow_exceptions = true)
24740 {
24741 basic_json result;
24742 auto ia = detail::input_adapter(std::move(first), std::move(last));
24743 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24744 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24745 return res ? result : basic_json(value_t::discarded);
24746 }
24747
24748 template<typename T>
24750 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24751 static basic_json from_bson(const T* ptr, std::size_t len,
24752 const bool strict = true,
24753 const bool allow_exceptions = true)
24754 {
24755 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24756 }
24757
24759 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24760 static basic_json from_bson(detail::span_input_adapter&& i,
24761 const bool strict = true,
24762 const bool allow_exceptions = true)
24763 {
24764 basic_json result;
24765 auto ia = i.get();
24766 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24767 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24768 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24769 return res ? result : basic_json(value_t::discarded);
24770 }
24771
24772
24774 // JSON Pointer support //
24776
24779
24783 {
24784 return ptr.get_unchecked(this);
24785 }
24786
24787 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24788 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24789 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24790 {
24791 return ptr.get_unchecked(this);
24792 }
24793
24797 {
24798 return ptr.get_unchecked(this);
24799 }
24800
24801 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24802 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24803 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24804 {
24805 return ptr.get_unchecked(this);
24806 }
24807
24811 {
24812 return ptr.get_checked(this);
24813 }
24814
24815 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24816 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24817 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24818 {
24819 return ptr.get_checked(this);
24820 }
24821
24825 {
24826 return ptr.get_checked(this);
24827 }
24828
24829 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24830 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24831 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24832 {
24833 return ptr.get_checked(this);
24834 }
24835
24839 {
24840 basic_json result(value_t::object);
24841 json_pointer::flatten("", *this, result);
24842 return result;
24843 }
24844
24848 {
24849 return json_pointer::unflatten(*this);
24850 }
24851
24853
24855 // JSON Patch functions //
24857
24860
24863 void patch_inplace(const basic_json& json_patch)
24864 {
24865 basic_json& result = *this;
24866 // the valid JSON Patch operations
24867 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24868
24869 const auto get_op = [](const string_t& op)
24870 {
24871 if (op == "add")
24872 {
24873 return patch_operations::add;
24874 }
24875 if (op == "remove")
24876 {
24877 return patch_operations::remove;
24878 }
24879 if (op == "replace")
24880 {
24881 return patch_operations::replace;
24882 }
24883 if (op == "move")
24884 {
24885 return patch_operations::move;
24886 }
24887 if (op == "copy")
24888 {
24889 return patch_operations::copy;
24890 }
24891 if (op == "test")
24892 {
24893 return patch_operations::test;
24894 }
24895
24896 return patch_operations::invalid;
24897 };
24898
24899 // wrapper for "add" operation; add value at ptr
24900 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24901 {
24902 // adding to the root of the target document means replacing it
24903 if (ptr.empty())
24904 {
24905 result = val;
24906 return;
24907 }
24908
24909 // make sure the top element of the pointer exists
24910 json_pointer const top_pointer = ptr.top();
24911 if (top_pointer != ptr)
24912 {
24913 result.at(top_pointer);
24914 }
24915
24916 // get reference to the parent of the JSON pointer ptr
24917 const auto last_path = ptr.back();
24918 ptr.pop_back();
24919 // parent must exist when performing patch add per RFC6902 specs
24920 basic_json& parent = result.at(ptr);
24921
24922 switch (parent.m_data.m_type)
24923 {
24924 case value_t::null:
24925 case value_t::object:
24926 {
24927 // use operator[] to add value
24928 parent[last_path] = val;
24929 break;
24930 }
24931
24932 case value_t::array:
24933 {
24934 if (last_path == "-")
24935 {
24936 // special case: append to back
24937 parent.push_back(val);
24938 }
24939 else
24940 {
24941 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24942 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24943 {
24944 // avoid undefined behavior
24945 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24946 }
24947
24948 // default case: insert add offset
24949 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24950 }
24951 break;
24952 }
24953
24954 // if there exists a parent, it cannot be primitive
24955 case value_t::string: // LCOV_EXCL_LINE
24956 case value_t::boolean: // LCOV_EXCL_LINE
24957 case value_t::number_integer: // LCOV_EXCL_LINE
24958 case value_t::number_unsigned: // LCOV_EXCL_LINE
24959 case value_t::number_float: // LCOV_EXCL_LINE
24960 case value_t::binary: // LCOV_EXCL_LINE
24961 case value_t::discarded: // LCOV_EXCL_LINE
24962 default: // LCOV_EXCL_LINE
24963 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24964 }
24965 };
24966
24967 // wrapper for "remove" operation; remove value at ptr
24968 const auto operation_remove = [this, & result](json_pointer & ptr)
24969 {
24970 // get reference to the parent of the JSON pointer ptr
24971 const auto last_path = ptr.back();
24972 ptr.pop_back();
24973 basic_json& parent = result.at(ptr);
24974
24975 // remove child
24976 if (parent.is_object())
24977 {
24978 // perform range check
24979 auto it = parent.find(last_path);
24980 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24981 {
24982 parent.erase(it);
24983 }
24984 else
24985 {
24986 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24987 }
24988 }
24989 else if (parent.is_array())
24990 {
24991 // note erase performs range check
24992 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24993 }
24994 };
24995
24996 // type check: top level value must be an array
24997 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24998 {
24999 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
25000 }
25001
25002 // iterate and apply the operations
25003 for (const auto& val : json_patch)
25004 {
25005 // wrapper to get a value for an operation
25006 const auto get_value = [&val](const string_t& op,
25007 const string_t& member,
25008 bool string_type) -> basic_json &
25009 {
25010 // find value
25011 auto it = val.m_data.m_value.object->find(member);
25012
25013 // context-sensitive error message
25014 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
25015
25016 // check if the desired value is present
25017 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
25018 {
25019 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25020 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
25021 }
25022
25023 // check if the result is of type string
25024 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
25025 {
25026 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25027 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
25028 }
25029
25030 // no error: return value
25031 return it->second;
25032 };
25033
25034 // type check: every element of the array must be an object
25035 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
25036 {
25037 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
25038 }
25039
25040 // collect mandatory members
25041 const auto op = get_value("op", "op", true).template get<string_t>();
25042 const auto path = get_value(op, "path", true).template get<string_t>();
25043 json_pointer ptr(path);
25044
25045 switch (get_op(op))
25046 {
25047 case patch_operations::add:
25048 {
25049 operation_add(ptr, get_value("add", "value", false));
25050 break;
25051 }
25052
25053 case patch_operations::remove:
25054 {
25055 operation_remove(ptr);
25056 break;
25057 }
25058
25059 case patch_operations::replace:
25060 {
25061 // the "path" location must exist - use at()
25062 result.at(ptr) = get_value("replace", "value", false);
25063 break;
25064 }
25065
25066 case patch_operations::move:
25067 {
25068 const auto from_path = get_value("move", "from", true).template get<string_t>();
25069 json_pointer from_ptr(from_path);
25070
25071 // the "from" location must exist - use at()
25072 basic_json const v = result.at(from_ptr);
25073
25074 // The move operation is functionally identical to a
25075 // "remove" operation on the "from" location, followed
25076 // immediately by an "add" operation at the target
25077 // location with the value that was just removed.
25078 operation_remove(from_ptr);
25079 operation_add(ptr, v);
25080 break;
25081 }
25082
25083 case patch_operations::copy:
25084 {
25085 const auto from_path = get_value("copy", "from", true).template get<string_t>();
25086 const json_pointer from_ptr(from_path);
25087
25088 // the "from" location must exist - use at()
25089 basic_json const v = result.at(from_ptr);
25090
25091 // The copy is functionally identical to an "add"
25092 // operation at the target location using the value
25093 // specified in the "from" member.
25094 operation_add(ptr, v);
25095 break;
25096 }
25097
25098 case patch_operations::test:
25099 {
25100 bool success = false;
25101 JSON_TRY
25102 {
25103 // check if "value" matches the one at "path"
25104 // the "path" location must exist - use at()
25105 success = (result.at(ptr) == get_value("test", "value", false));
25106 }
25108 {
25109 // ignore out of range errors: success remains false
25110 }
25111
25112 // throw an exception if the test fails
25113 if (JSON_HEDLEY_UNLIKELY(!success))
25114 {
25115 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
25116 }
25117
25118 break;
25119 }
25120
25121 case patch_operations::invalid:
25122 default:
25123 {
25124 // op must be "add", "remove", "replace", "move", "copy", or
25125 // "test"
25126 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
25127 }
25128 }
25129 }
25130 }
25131
25134 basic_json patch(const basic_json& json_patch) const
25135 {
25136 basic_json result = *this;
25137 result.patch_inplace(json_patch);
25138 return result;
25139 }
25140
25144 static basic_json diff(const basic_json& source, const basic_json& target,
25145 const string_t& path = "")
25146 {
25147 // the patch
25148 basic_json result(value_t::array);
25149
25150 // if the values are the same, return an empty patch
25151 if (source == target)
25152 {
25153 return result;
25154 }
25155
25156 if (source.type() != target.type())
25157 {
25158 // different types: replace value
25159 result.push_back(
25160 {
25161 {"op", "replace"}, {"path", path}, {"value", target}
25162 });
25163 return result;
25164 }
25165
25166 switch (source.type())
25167 {
25168 case value_t::array:
25169 {
25170 // first pass: traverse common elements
25171 std::size_t i = 0;
25172 while (i < source.size() && i < target.size())
25173 {
25174 // recursive call to compare array values at index i
25175 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
25176 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25177 ++i;
25178 }
25179
25180 // We now reached the end of at least one array
25181 // in a second pass, traverse the remaining elements
25182
25183 // remove my remaining elements
25184 const auto end_index = static_cast<difference_type>(result.size());
25185 while (i < source.size())
25186 {
25187 // add operations in reverse order to avoid invalid
25188 // indices
25189 result.insert(result.begin() + end_index, object(
25190 {
25191 {"op", "remove"},
25192 {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
25193 }));
25194 ++i;
25195 }
25196
25197 // add other remaining elements
25198 while (i < target.size())
25199 {
25200 result.push_back(
25201 {
25202 {"op", "add"},
25203 {"path", detail::concat<string_t>(path, "/-")},
25204 {"value", target[i]}
25205 });
25206 ++i;
25207 }
25208
25209 break;
25210 }
25211
25212 case value_t::object:
25213 {
25214 // first pass: traverse this object's elements
25215 for (auto it = source.cbegin(); it != source.cend(); ++it)
25216 {
25217 // escape the key name to be used in a JSON patch
25218 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25219
25220 if (target.find(it.key()) != target.end())
25221 {
25222 // recursive call to compare object values at key it
25223 auto temp_diff = diff(it.value(), target[it.key()], path_key);
25224 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25225 }
25226 else
25227 {
25228 // found a key that is not in o -> remove it
25229 result.push_back(object(
25230 {
25231 {"op", "remove"}, {"path", path_key}
25232 }));
25233 }
25234 }
25235
25236 // second pass: traverse other object's elements
25237 for (auto it = target.cbegin(); it != target.cend(); ++it)
25238 {
25239 if (source.find(it.key()) == source.end())
25240 {
25241 // found a key that is not in this -> add it
25242 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25243 result.push_back(
25244 {
25245 {"op", "add"}, {"path", path_key},
25246 {"value", it.value()}
25247 });
25248 }
25249 }
25250
25251 break;
25252 }
25253
25254 case value_t::null:
25255 case value_t::string:
25256 case value_t::boolean:
25257 case value_t::number_integer:
25258 case value_t::number_unsigned:
25259 case value_t::number_float:
25260 case value_t::binary:
25261 case value_t::discarded:
25262 default:
25263 {
25264 // both primitive types: replace value
25265 result.push_back(
25266 {
25267 {"op", "replace"}, {"path", path}, {"value", target}
25268 });
25269 break;
25270 }
25271 }
25272
25273 return result;
25274 }
25275
25276
25278 // JSON Merge Patch functions //
25280
25283
25286 void merge_patch(const basic_json& apply_patch)
25287 {
25288 if (apply_patch.is_object())
25289 {
25290 if (!is_object())
25291 {
25292 *this = object();
25293 }
25294 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25295 {
25296 if (it.value().is_null())
25297 {
25298 erase(it.key());
25299 }
25300 else
25301 {
25302 operator[](it.key()).merge_patch(it.value());
25303 }
25304 }
25305 }
25306 else
25307 {
25308 *this = apply_patch;
25309 }
25310 }
25311
25313};
25314
25319{
25320 return j.dump();
25321}
25322
25323inline namespace literals
25324{
25325inline namespace json_literals
25326{
25327
25331#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25332 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
25333#else
25334 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
25335#endif
25336{
25337 return nlohmann::json::parse(s, s + n);
25338}
25339
25343#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25344 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
25345#else
25346 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
25347#endif
25348{
25349 return nlohmann::json::json_pointer(std::string(s, n));
25350}
25351
25352} // namespace json_literals
25353} // namespace literals
25355
25357// nonmember support //
25359
25360namespace std // NOLINT(cert-dcl58-cpp)
25361{
25362
25366struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
25367{
25368 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
25369 {
25370 return nlohmann::detail::hash(j);
25371 }
25372};
25373
25374// specialization for std::less<value_t>
25375template<>
25376struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
25377{
25382 bool operator()(::nlohmann::detail::value_t lhs,
25383 ::nlohmann::detail::value_t rhs) const noexcept
25384 {
25385#if JSON_HAS_THREE_WAY_COMPARISON
25386 return std::is_lt(lhs <=> rhs); // *NOPAD*
25387#else
25388 return ::nlohmann::detail::operator<(lhs, rhs);
25389#endif
25390 }
25391};
25392
25393// C++20 prohibit function specialization in the std namespace.
25394#ifndef JSON_HAS_CPP_20
25395
25399inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
25400 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
25401 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
25402{
25403 j1.swap(j2);
25404}
25405
25406#endif
25407
25408} // namespace std
25409
25410#if JSON_USE_GLOBAL_UDLS
25411 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25412 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25413 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25414 #else
25415 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25416 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25417 #endif
25418#endif
25419
25420// #include <nlohmann/detail/macro_unscope.hpp>
25421// __ _____ _____ _____
25422// __| | __| | | | JSON for Modern C++
25423// | | |__ | | | | | | version 3.12.0
25424// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25425//
25426// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25427// SPDX-License-Identifier: MIT
25428
25429
25430
25431// restore clang diagnostic settings
25432#if defined(__clang__)
25433 #pragma clang diagnostic pop
25434#endif
25435
25436// clean up
25437#undef JSON_ASSERT
25438#undef JSON_INTERNAL_CATCH
25439#undef JSON_THROW
25440#undef JSON_PRIVATE_UNLESS_TESTED
25441#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25442#undef NLOHMANN_BASIC_JSON_TPL
25443#undef JSON_EXPLICIT
25444#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
25445#undef JSON_INLINE_VARIABLE
25446#undef JSON_NO_UNIQUE_ADDRESS
25447#undef JSON_DISABLE_ENUM_SERIALIZATION
25448#undef JSON_USE_GLOBAL_UDLS
25449
25450#ifndef JSON_TEST_KEEP_MACROS
25451 #undef JSON_CATCH
25452 #undef JSON_TRY
25453 #undef JSON_HAS_CPP_11
25454 #undef JSON_HAS_CPP_14
25455 #undef JSON_HAS_CPP_17
25456 #undef JSON_HAS_CPP_20
25457 #undef JSON_HAS_CPP_23
25458 #undef JSON_HAS_CPP_26
25459 #undef JSON_HAS_FILESYSTEM
25460 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
25461 #undef JSON_HAS_THREE_WAY_COMPARISON
25462 #undef JSON_HAS_RANGES
25463 #undef JSON_HAS_STATIC_RTTI
25464 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
25465#endif
25466
25467// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25468// __ _____ _____ _____
25469// __| | __| | | | JSON for Modern C++
25470// | | |__ | | | | | | version 3.12.0
25471// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25472//
25473// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25474// SPDX-License-Identifier: MIT
25475
25476
25477
25478#undef JSON_HEDLEY_ALWAYS_INLINE
25479#undef JSON_HEDLEY_ARM_VERSION
25480#undef JSON_HEDLEY_ARM_VERSION_CHECK
25481#undef JSON_HEDLEY_ARRAY_PARAM
25482#undef JSON_HEDLEY_ASSUME
25483#undef JSON_HEDLEY_BEGIN_C_DECLS
25484#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25485#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25486#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25487#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25488#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25489#undef JSON_HEDLEY_CLANG_HAS_FEATURE
25490#undef JSON_HEDLEY_CLANG_HAS_WARNING
25491#undef JSON_HEDLEY_COMPCERT_VERSION
25492#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25493#undef JSON_HEDLEY_CONCAT
25494#undef JSON_HEDLEY_CONCAT3
25495#undef JSON_HEDLEY_CONCAT3_EX
25496#undef JSON_HEDLEY_CONCAT_EX
25497#undef JSON_HEDLEY_CONST
25498#undef JSON_HEDLEY_CONSTEXPR
25499#undef JSON_HEDLEY_CONST_CAST
25500#undef JSON_HEDLEY_CPP_CAST
25501#undef JSON_HEDLEY_CRAY_VERSION
25502#undef JSON_HEDLEY_CRAY_VERSION_CHECK
25503#undef JSON_HEDLEY_C_DECL
25504#undef JSON_HEDLEY_DEPRECATED
25505#undef JSON_HEDLEY_DEPRECATED_FOR
25506#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25507#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25508#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25509#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25510#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25511#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
25512#undef JSON_HEDLEY_DIAGNOSTIC_POP
25513#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25514#undef JSON_HEDLEY_DMC_VERSION
25515#undef JSON_HEDLEY_DMC_VERSION_CHECK
25516#undef JSON_HEDLEY_EMPTY_BASES
25517#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25518#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25519#undef JSON_HEDLEY_END_C_DECLS
25520#undef JSON_HEDLEY_FLAGS
25521#undef JSON_HEDLEY_FLAGS_CAST
25522#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25523#undef JSON_HEDLEY_GCC_HAS_BUILTIN
25524#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25525#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25526#undef JSON_HEDLEY_GCC_HAS_EXTENSION
25527#undef JSON_HEDLEY_GCC_HAS_FEATURE
25528#undef JSON_HEDLEY_GCC_HAS_WARNING
25529#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25530#undef JSON_HEDLEY_GCC_VERSION
25531#undef JSON_HEDLEY_GCC_VERSION_CHECK
25532#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25533#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25534#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25535#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25536#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25537#undef JSON_HEDLEY_GNUC_HAS_FEATURE
25538#undef JSON_HEDLEY_GNUC_HAS_WARNING
25539#undef JSON_HEDLEY_GNUC_VERSION
25540#undef JSON_HEDLEY_GNUC_VERSION_CHECK
25541#undef JSON_HEDLEY_HAS_ATTRIBUTE
25542#undef JSON_HEDLEY_HAS_BUILTIN
25543#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25544#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25545#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25546#undef JSON_HEDLEY_HAS_EXTENSION
25547#undef JSON_HEDLEY_HAS_FEATURE
25548#undef JSON_HEDLEY_HAS_WARNING
25549#undef JSON_HEDLEY_IAR_VERSION
25550#undef JSON_HEDLEY_IAR_VERSION_CHECK
25551#undef JSON_HEDLEY_IBM_VERSION
25552#undef JSON_HEDLEY_IBM_VERSION_CHECK
25553#undef JSON_HEDLEY_IMPORT
25554#undef JSON_HEDLEY_INLINE
25555#undef JSON_HEDLEY_INTEL_CL_VERSION
25556#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
25557#undef JSON_HEDLEY_INTEL_VERSION
25558#undef JSON_HEDLEY_INTEL_VERSION_CHECK
25559#undef JSON_HEDLEY_IS_CONSTANT
25560#undef JSON_HEDLEY_IS_CONSTEXPR_
25561#undef JSON_HEDLEY_LIKELY
25562#undef JSON_HEDLEY_MALLOC
25563#undef JSON_HEDLEY_MCST_LCC_VERSION
25564#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
25565#undef JSON_HEDLEY_MESSAGE
25566#undef JSON_HEDLEY_MSVC_VERSION
25567#undef JSON_HEDLEY_MSVC_VERSION_CHECK
25568#undef JSON_HEDLEY_NEVER_INLINE
25569#undef JSON_HEDLEY_NON_NULL
25570#undef JSON_HEDLEY_NO_ESCAPE
25571#undef JSON_HEDLEY_NO_RETURN
25572#undef JSON_HEDLEY_NO_THROW
25573#undef JSON_HEDLEY_NULL
25574#undef JSON_HEDLEY_PELLES_VERSION
25575#undef JSON_HEDLEY_PELLES_VERSION_CHECK
25576#undef JSON_HEDLEY_PGI_VERSION
25577#undef JSON_HEDLEY_PGI_VERSION_CHECK
25578#undef JSON_HEDLEY_PREDICT
25579#undef JSON_HEDLEY_PRINTF_FORMAT
25580#undef JSON_HEDLEY_PRIVATE
25581#undef JSON_HEDLEY_PUBLIC
25582#undef JSON_HEDLEY_PURE
25583#undef JSON_HEDLEY_REINTERPRET_CAST
25584#undef JSON_HEDLEY_REQUIRE
25585#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25586#undef JSON_HEDLEY_REQUIRE_MSG
25587#undef JSON_HEDLEY_RESTRICT
25588#undef JSON_HEDLEY_RETURNS_NON_NULL
25589#undef JSON_HEDLEY_SENTINEL
25590#undef JSON_HEDLEY_STATIC_ASSERT
25591#undef JSON_HEDLEY_STATIC_CAST
25592#undef JSON_HEDLEY_STRINGIFY
25593#undef JSON_HEDLEY_STRINGIFY_EX
25594#undef JSON_HEDLEY_SUNPRO_VERSION
25595#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25596#undef JSON_HEDLEY_TINYC_VERSION
25597#undef JSON_HEDLEY_TINYC_VERSION_CHECK
25598#undef JSON_HEDLEY_TI_ARMCL_VERSION
25599#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25600#undef JSON_HEDLEY_TI_CL2000_VERSION
25601#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25602#undef JSON_HEDLEY_TI_CL430_VERSION
25603#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25604#undef JSON_HEDLEY_TI_CL6X_VERSION
25605#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25606#undef JSON_HEDLEY_TI_CL7X_VERSION
25607#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25608#undef JSON_HEDLEY_TI_CLPRU_VERSION
25609#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25610#undef JSON_HEDLEY_TI_VERSION
25611#undef JSON_HEDLEY_TI_VERSION_CHECK
25612#undef JSON_HEDLEY_UNAVAILABLE
25613#undef JSON_HEDLEY_UNLIKELY
25614#undef JSON_HEDLEY_UNPREDICTABLE
25615#undef JSON_HEDLEY_UNREACHABLE
25616#undef JSON_HEDLEY_UNREACHABLE_RETURN
25617#undef JSON_HEDLEY_VERSION
25618#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25619#undef JSON_HEDLEY_VERSION_DECODE_MINOR
25620#undef JSON_HEDLEY_VERSION_DECODE_REVISION
25621#undef JSON_HEDLEY_VERSION_ENCODE
25622#undef JSON_HEDLEY_WARNING
25623#undef JSON_HEDLEY_WARN_UNUSED_RESULT
25624#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25625#undef JSON_HEDLEY_FALL_THROUGH
25626
25627
25628
25629#endif // INCLUDE_NLOHMANN_JSON_HPP_
nlohmann::json json
Definition CMapTool.cpp:5
namespace for Niels Lohmann
Definition json.hpp:20203
constexpr bool is_string() const noexcept
Definition json.hpp:21502
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:22737
detail::cbor_tag_handler_t cbor_tag_handler_t
Definition json.hpp:20277
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:22303
size_type size() const noexcept
Definition json.hpp:23078
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:24542
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
Definition json.hpp:21875
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22935
reference back()
access the last element
Definition json.hpp:22541
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
Definition json.hpp:20942
detail::parse_error parse_error
Definition json.hpp:20296
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22951
detail::input_format_t input_format_t
Definition json.hpp:20283
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.hpp:25134
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
Definition json.hpp:24301
const_reference front() const
access the first element
Definition json.hpp:22534
constexpr bool is_array() const noexcept
Definition json.hpp:21495
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
Definition json.hpp:23596
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22484
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22854
iter_impl< const basic_json > const_iterator
Definition json.hpp:20337
constexpr bool is_number_integer() const noexcept
Definition json.hpp:21467
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
Definition json.hpp:20341
data(size_type cnt, const basic_json &val)
Definition json.hpp:24346
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:24737
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24782
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
Definition json.hpp:20332
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:21439
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:22327
detail::error_handler_t error_handler_t
Definition json.hpp:20275
const value_type & const_reference
Definition json.hpp:20319
detail::invalid_iterator invalid_iterator
Definition json.hpp:20297
void swap(binary_t &other)
exchanges the values
Definition json.hpp:23673
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:23117
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:23542
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:21976
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:21516
JSON_PRIVATE_UNLESS_TESTED const_reference rhs
Definition json.hpp:23791
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:23333
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:23221
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:22272
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:23023
const_reference back() const
access the last element
Definition json.hpp:22550
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:22632
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:23278
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:23613
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:24638
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:21084
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:23445
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:24722
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:20347
nlohmann::byte_container_with_subtype< std::vector< std::uint8_t > > binary_t
Definition json.hpp:20472
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:22135
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:21474
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:23549
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:24501
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22958
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:23317
detail::parser_callback_t< basic_json > parser_callback_t
Definition json.hpp:20909
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:21125
ValueType & get_to(ValueType &v) const
Definition json.hpp:21942
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24437
detail::parse_event_t parse_event_t
Definition json.hpp:20905
JSON_PRIVATE_UNLESS_TESTED const_reference bool inverse
Definition json.hpp:23791
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:22382
const_iterator cend() const noexcept
Definition json.hpp:22942
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:24692
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24824
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:21095
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:20930
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:24526
basic_json flatten() const
return flattened JSON value
Definition json.hpp:24838
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:24653
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:22748
JSON_PRIVATE_UNLESS_TESTED const_reference bool static SAX bool sax_parse(InputType &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true, const bool ignore_comments=false, const bool ignore_trailing_commas=false)
Definition json.hpp:24222
std::vector< basic_json, std::allocator< basic_json > > array_t
Definition json.hpp:20448
nlohmann::ordered_map< std::string, basic_json, default_object_comparator_t, std::allocator< std::pair< const std::string, basic_json > > > object_t
Definition json.hpp:20440
const binary_t & get_binary() const
get a binary value
Definition json.hpp:22047
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:23465
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.hpp:24863
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22435
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24796
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
Definition json.hpp:20281
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:22871
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:24407
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
Definition json.hpp:24517
iterator find(const typename object_t::key_type &key)
Definition json.hpp:22784
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition json.hpp:21073
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.hpp:24471
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:22173
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:20355
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:21132
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:22798
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:24398
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:22562
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:23418
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22357
std::allocator< basic_json > allocator_type
Definition json.hpp:20327
typename std::allocator_traits< allocator_type >::pointer pointer
Definition json.hpp:20330
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition json.hpp:21403
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:25286
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.hpp:21929
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.hpp:24483
reference operator[](T *key)
Definition json.hpp:22288
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:22069
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:22814
constexpr bool is_number_float() const noexcept
Definition json.hpp:21481
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:22965
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:24444
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24810
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const string_t &path="")
creates a diff as a JSON patch
Definition json.hpp:25144
std::less< std::string > default_object_comparator_t
Definition json.hpp:20435
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23309
const_iterator cbegin() const noexcept
Definition json.hpp:22917
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:22250
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:21687
~basic_json() noexcept
destructor
Definition json.hpp:21385
detail::out_of_range out_of_range
Definition json.hpp:20299
const_reverse_iterator crend() const noexcept
Definition json.hpp:22986
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.hpp:21014
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:23689
binary_t & get_binary()
get a binary value
Definition json.hpp:22035
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.hpp:22910
constexpr bool is_number() const noexcept
Definition json.hpp:21460
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:23516
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:24584
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21916
const_reference operator[](T *key) const
Definition json.hpp:22294
reference operator[](size_type idx)
access specified array element
Definition json.hpp:22191
basic_json(const JsonRef &ref)
Definition json.hpp:21253
adl_serializer< T, SFINAE > json_serializer
Definition json.hpp:20273
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition json.hpp:21356
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
Definition json.hpp:22998
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:24463
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
Definition json.hpp:21953
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:21676
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:22153
constexpr bool is_binary() const noexcept
Definition json.hpp:21509
void swap(object_t &other)
exchanges the values
Definition json.hpp:23641
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:24847
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:23496
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.hpp:24492
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:21106
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:23016
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:23039
void swap(array_t &other)
exchanges the values
Definition json.hpp:23625
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:22755
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:23246
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:22878
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:21425
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:23342
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22458
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:21117
detail::bjdata_version_t bjdata_version_t
Definition json.hpp:20279
data() noexcept=default
friend class ::nlohmann::detail::parser
Definition json.hpp:20213
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:23254
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22408
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:22115
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:24707
const_reverse_iterator crbegin() const noexcept
Definition json.hpp:22979
json_sax< basic_json > json_sax_t
Definition json.hpp:20285
constexpr bool is_boolean() const noexcept
Definition json.hpp:21453
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22844
reference front()
access the first element
Definition json.hpp:22527
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:21432
constexpr bool is_null() const noexcept
Definition json.hpp:21446
void clear() noexcept
clears the contents
Definition json.hpp:23160
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:24455
detail::other_error other_error
Definition json.hpp:20300
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:21330
iter_impl< basic_json > iterator
Definition json.hpp:20335
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:20922
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:22237
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:23438
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.hpp:22972
friend std::istream & operator>>(std::istream &i, basic_json &j)
Definition json.hpp:24286
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24421
void swap(string_t &other)
exchanges the values
Definition json.hpp:23657
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:20956
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
Definition json.hpp:20339
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:22092
detail::actual_object_comparator_t< basic_json > object_comparator_t
Definition json.hpp:20476
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:21257
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23286
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:23367
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:24414
constexpr bool is_object() const noexcept
Definition json.hpp:21488
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24430
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:24599
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.hpp:23399
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:21144
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:22862
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
Definition json.hpp:24510
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:22830
::nlohmann::json_pointer< std::string > json_pointer
Definition json.hpp:20271
bool operator!=(const byte_container_with_subtype &rhs) const
Definition json.hpp:6279
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:6245
std::uint64_t subtype_type
Definition json.hpp:6242
bool operator==(const byte_container_with_subtype &rhs) const
Definition json.hpp:6273
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6267
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6255
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:6294
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:6260
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:6301
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:6250
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:6286
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:6308
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9892
binary_reader(const binary_reader &)=delete
binary_reader(binary_reader &&)=default
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:9908
binary_reader & operator=(const binary_reader &)=delete
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition json.hpp:9929
binary_reader & operator=(binary_reader &&)=default
void write_bson(const BasicJsonType &j)
Definition json.hpp:15883
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:17623
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true, const bool use_bjdata=false, const bjdata_version_t bjdata_version=bjdata_version_t::draft2)
Definition json.hpp:16563
static CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:17630
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:15874
static constexpr CharType to_char_type(InputCharType x) noexcept
Definition json.hpp:17665
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:16236
void write_cbor(const BasicJsonType &j)
Definition json.hpp:15912
general exception of the basic_json class
Definition json.hpp:4540
exception(int id_, const char *what_arg)
Definition json.hpp:4553
const int id
the id of the exception
Definition json.hpp:4549
static std::string diagnostics(std::nullptr_t)
Definition json.hpp:4560
static std::string name(const std::string &ename, int id_)
Definition json.hpp:4555
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4543
static std::string diagnostics(const BasicJsonType *leaf_element)
Definition json.hpp:4566
file_input_adapter(const file_input_adapter &)=delete
file_input_adapter(std::FILE *f) noexcept
Definition json.hpp:6547
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6560
file_input_adapter(file_input_adapter &&) noexcept=default
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6567
input_stream_adapter & operator=(input_stream_adapter &&)=delete
input_stream_adapter(input_stream_adapter &&rhs) noexcept
Definition json.hpp:6610
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6632
std::char_traits< char >::int_type get_character()
Definition json.hpp:6620
input_stream_adapter(const input_stream_adapter &)=delete
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(std::istream &i)
Definition json.hpp:6601
exception indicating errors with iterators
Definition json.hpp:4709
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4712
~iter_impl()=default
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:14265
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:13819
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:14210
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:13809
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:14152
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:14192
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:14256
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:14062
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:14365
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:14103
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:14000
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:14219
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14327
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
Definition json.hpp:13714
pointer operator->() const
dereference the iterator
Definition json.hpp:13958
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:14298
iter_impl(iter_impl &&) noexcept=default
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:14276
reference value() const
return the value of an iterator
Definition json.hpp:14381
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:14201
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:14011
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:13914
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14287
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
Definition json.hpp:13718
iter_impl()=default
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:13794
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:14143
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:14051
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:13784
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:13875
iteration_proxy_value operator++(int) &
Definition json.hpp:5557
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5566
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5572
std::ptrdiff_t difference_type
Definition json.hpp:5503
iteration_proxy_value(IteratorType it, std::size_t array_index_=0) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_default_constructible< string_type >::value)
Definition json.hpp:5524
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5549
std::forward_iterator_tag iterator_category
Definition json.hpp:5507
iteration_proxy_value value_type
Definition json.hpp:5504
iteration_proxy_value(iteration_proxy_value &&) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_move_constructible< string_type >::value)=default
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5614
const string_type & key() const
return key of the iterator
Definition json.hpp:5578
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
Definition json.hpp:5508
proxy class for the items() function
Definition json.hpp:5622
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5647
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:5641
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5631
iteration_proxy & operator=(iteration_proxy const &)=default
char_traits< char_type >::int_type get_character()
Definition json.hpp:6661
iterator_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6657
typename std::iterator_traits< IteratorType >::value_type char_type
Definition json.hpp:6655
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6675
json_ref(json_ref &&) noexcept=default
json_ref(const value_type &value)
Definition json.hpp:15603
json_ref(value_type &&value)
Definition json.hpp:15599
value_type const & operator*() const
Definition json.hpp:15634
value_type const * operator->() const
Definition json.hpp:15639
json_ref(std::initializer_list< json_ref > init)
Definition json.hpp:15607
json_ref(Args &&... args)
Definition json.hpp:15614
value_type moved_or_copied() const
Definition json.hpp:15625
BasicJsonType value_type
Definition json.hpp:15597
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:14460
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:14472
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:14466
std::ptrdiff_t difference_type
Definition json.hpp:14446
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:14484
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14508
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:14514
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:14502
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:14450
reference value() const
return the value of an iterator
Definition json.hpp:14521
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:14457
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:14478
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:14448
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14496
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:14453
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:14490
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9610
bool binary(binary_t &)
Definition json.hpp:9645
bool number_integer(number_integer_t)
Definition json.hpp:9625
bool start_array(std::size_t=detail::unknown_size())
Definition json.hpp:9665
bool number_unsigned(number_unsigned_t)
Definition json.hpp:9630
bool start_object(std::size_t=detail::unknown_size())
Definition json.hpp:9650
bool string(string_t &)
Definition json.hpp:9640
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9613
bool number_float(number_float_t, const string_t &)
Definition json.hpp:9635
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition json.hpp:9675
bool key(string_t &)
Definition json.hpp:9655
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9609
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9611
typename BasicJsonType::string_t string_t
Definition json.hpp:9612
bool start_array(std::size_t len)
Definition json.hpp:9338
typename BasicJsonType::parser_callback_t parser_callback_t
Definition json.hpp:9177
typename BasicJsonType::parse_event_t parse_event_t
Definition json.hpp:9178
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.hpp:9209
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:9417
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9174
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
lexer< BasicJsonType, InputAdapterType > lexer_t
Definition json.hpp:9179
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:9215
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:9221
constexpr bool is_errored() const
Definition json.hpp:9429
json_sax_dom_callback_parser(BasicJsonType &r, parser_callback_t cb, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:9181
typename BasicJsonType::string_t string_t
Definition json.hpp:9175
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9173
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9172
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9176
bool start_object(std::size_t len)
Definition json.hpp:9239
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
SAX implementation to create a JSON value from SAX events
Definition json.hpp:8864
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:8913
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:8907
json_sax_dom_parser(const json_sax_dom_parser &)=delete
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
bool binary(binary_t &val)
Definition json.hpp:8925
typename BasicJsonType::binary_t binary_t
Definition json.hpp:8870
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:8878
bool start_object(std::size_t len)
Definition json.hpp:8931
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:8866
bool key(string_t &val)
Definition json.hpp:8954
typename BasicJsonType::string_t string_t
Definition json.hpp:8869
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:8867
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:9022
lexer< BasicJsonType, InputAdapterType > lexer_t
Definition json.hpp:8871
bool boolean(bool val)
Definition json.hpp:8895
bool start_array(std::size_t len)
Definition json.hpp:8982
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:8868
json_sax_dom_parser(json_sax_dom_parser &&)=default
constexpr bool is_errored() const
Definition json.hpp:9034
bool string(string_t &val)
Definition json.hpp:8919
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.hpp:8901
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition json.hpp:7131
token_type
token types for the parser
Definition json.hpp:7108
@ value_float
an floating point number – use get_number_float() for actual value
Definition json.hpp:7116
@ begin_array
the character for array begin [
Definition json.hpp:7117
@ value_string
a string – use get_string() for actual value
Definition json.hpp:7113
@ end_array
the character for array end ]
Definition json.hpp:7119
@ uninitialized
indicating the scanner is uninitialized
Definition json.hpp:7109
@ parse_error
indicating a parse error
Definition json.hpp:7123
@ value_integer
a signed integer – use get_number_integer() for actual value
Definition json.hpp:7115
@ value_separator
the value separator ,
Definition json.hpp:7122
@ end_object
the character for object end }
Definition json.hpp:7120
@ literal_true
the true literal
Definition json.hpp:7110
@ begin_object
the character for object begin {
Definition json.hpp:7118
@ value_unsigned
an unsigned integer – use get_number_unsigned() for actual value
Definition json.hpp:7114
@ literal_null
the null literal
Definition json.hpp:7112
@ end_of_input
indicating the end of the input buffer
Definition json.hpp:7124
@ name_separator
the name separator :
Definition json.hpp:7121
@ literal_or_value
a literal or the begin of a value (only for diagnostics)
Definition json.hpp:7125
@ literal_false
the false literal
Definition json.hpp:7111
lexical analysis
Definition json.hpp:7181
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:8563
void skip_whitespace()
Definition json.hpp:8577
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
Definition json.hpp:7192
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8550
std::string get_token_string() const
Definition json.hpp:8525
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8484
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8517
token_type scan()
Definition json.hpp:8586
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8490
typename lexer_base< BasicJsonType >::token_type token_type
Definition json.hpp:7190
lexer(lexer &&)=default
~lexer()=default
lexer & operator=(lexer &&)=default
lexer(const lexer &)=delete
lexer & operator=(lexer &)=delete
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:8502
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8496
exception indicating other library errors
Definition json.hpp:4761
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4764
exception indicating access out of the defined range
Definition json.hpp:4744
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4747
output_adapter(StringType &s)
Definition json.hpp:15825
output_adapter(std::basic_ostream< CharType > &s)
Definition json.hpp:15821
output_adapter(std::vector< CharType, AllocatorType > &vec)
Definition json.hpp:15817
output adapter for output streams
Definition json.hpp:15766
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:15778
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
Definition json.hpp:15768
void write_character(CharType c) override
Definition json.hpp:15772
output adapter for basic_string
Definition json.hpp:15791
void write_character(CharType c) override
Definition json.hpp:15797
output_string_adapter(StringType &s) noexcept
Definition json.hpp:15793
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:15803
output adapter for byte vectors
Definition json.hpp:15741
output_vector_adapter(std::vector< CharType, AllocatorType > &vec) noexcept
Definition json.hpp:15743
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:15753
void write_character(CharType c) override
Definition json.hpp:15747
exception indicating a parse error
Definition json.hpp:4656
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
Definition json.hpp:4668
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4676
const std::size_t byte
byte index of the parse error
Definition json.hpp:4693
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:13012
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:13072
bool sax_parse(SAX *sax, const bool strict=true)
Definition json.hpp:13080
parser(InputAdapterType &&adapter, parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool ignore_comments=false, const bool ignore_trailing_commas_=false)
a parser reading from an input adapter
Definition json.hpp:12988
primitive_iterator_t & operator++() noexcept
Definition json.hpp:13561
primitive_iterator_t & operator-=(difference_type n) noexcept
Definition json.hpp:13593
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.hpp:13528
primitive_iterator_t & operator--() noexcept
Definition json.hpp:13574
void set_end() noexcept
set iterator to a defined past the end
Definition json.hpp:13522
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13544
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.hpp:13534
primitive_iterator_t operator++(int) &noexcept
Definition json.hpp:13567
primitive_iterator_t & operator+=(difference_type n) noexcept
Definition json.hpp:13587
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13539
constexpr difference_type get_value() const noexcept
Definition json.hpp:13510
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13556
primitive_iterator_t operator+(difference_type n) noexcept
Definition json.hpp:13549
void set_begin() noexcept
set iterator to a defined beginning
Definition json.hpp:13516
primitive_iterator_t operator--(int) &noexcept
Definition json.hpp:13580
std::array< char, 512 > string_buffer
string buffer
Definition json.hpp:19786
std::uint8_t state
Definition json.hpp:19204
std::size_t bytes_after_last_accept
Definition json.hpp:19208
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:18877
JSON_PRIVATE_UNLESS_TESTED const bool ensure_ascii
Definition json.hpp:19202
std::size_t undumped_chars
Definition json.hpp:19209
const char thousands_sep
the locale's thousand separator character
Definition json.hpp:19781
const char decimal_point
the locale's decimal point character
Definition json.hpp:19783
serializer & operator=(const serializer &)=delete
~serializer()=default
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:19794
string_t indent_string
the indentation string
Definition json.hpp:19791
const std::lconv * loc
the locale
Definition json.hpp:19779
serializer & operator=(serializer &&)=delete
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition json.hpp:19776
const char indent_char
the indentation character
Definition json.hpp:19789
std::size_t bytes
Definition json.hpp:19205
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition json.hpp:18917
serializer(const serializer &)=delete
serializer(serializer &&)=delete
span_input_adapter(CharT b, std::size_t l)
Definition json.hpp:7023
span_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:7030
contiguous_bytes_input_adapter && get()
Definition json.hpp:7033
exception indicating executing a member function with a wrong type
Definition json.hpp:4727
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4730
std::size_t get_elements(T *, std::size_t=1)
Definition json.hpp:6858
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6839
wide_string_input_adapter(BaseInputAdapter base)
Definition json.hpp:6836
JSON Pointer defines a string syntax for identifying a specific value within a JSON document
Definition json.hpp:14616
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition json.hpp:14711
typename string_t_helper< RefStringType >::type string_t
Definition json.hpp:14638
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition json.hpp:14718
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:14642
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:14777
void pop_back()
remove last reference token
Definition json.hpp:14739
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:14648
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:14696
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14770
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:14678
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition json.hpp:14703
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:14725
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:14688
friend class json_pointer
Definition json.hpp:14622
const string_t & back() const
return last reference token
Definition json.hpp:14751
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:14669
friend class basic_json
Definition json.hpp:14619
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14763
decltype( get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition json.hpp:5693
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition json.hpp:2622
#define JSON_HEDLEY_CONST
Definition json.hpp:1829
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition json.hpp:1113
#define JSON_INLINE_VARIABLE
Definition json.hpp:2521
#define JSON_HEDLEY_WARN_UNUSED_RESULT
Definition json.hpp:1459
#define JSON_PRIVATE_UNLESS_TESTED
Definition json.hpp:2581
#define NLOHMANN_JSON_VERSION_PATCH
Definition json.hpp:70
#define JSON_HEDLEY_LIKELY(expr)
Definition json.hpp:1724
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15511
#define JSON_HEDLEY_NON_NULL(...)
Definition json.hpp:1617
#define JSON_INTERNAL_CATCH(exception)
Definition json.hpp:2548
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition json.hpp:25318
#define JSON_HEDLEY_RETURNS_NON_NULL
Definition json.hpp:2058
#define JSON_CATCH(exception)
Definition json.hpp:2547
#define JSON_ASSERT(x)
Definition json.hpp:2574
#define JSON_THROW(exception)
Definition json.hpp:2545
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
Definition json.hpp:81
#define NLOHMANN_JSON_VERSION_MAJOR
Definition json.hpp:68
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15561
#define NLOHMANN_BASIC_JSON_TPL
Definition json.hpp:2632
#define JSON_HEDLEY_UNLIKELY(expr)
Definition json.hpp:1725
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
Definition json.hpp:12867
#define JSON_TRY
Definition json.hpp:2546
#define NLOHMANN_JSON_NAMESPACE_END
Definition json.hpp:155
#define JSON_NO_UNIQUE_ADDRESS
Definition json.hpp:2527
basic_json< nlohmann::ordered_map > ordered_json
specialization that maintains the insertion order of object keys
Definition json.hpp:3563
#define NLOHMANN_JSON_VERSION_MINOR
Definition json.hpp:69
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
Definition json.hpp:2916
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15536
#define NLOHMANN_JSON_NAMESPACE_BEGIN
Definition json.hpp:145
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
Definition json.hpp:12864
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition json.hpp:1114
#define JSON_EXPLICIT
Definition json.hpp:2953
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
Definition json.hpp:1407
#define JSON_HEDLEY_PURE
Definition json.hpp:1798
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
Definition json.hpp:23714
#define JSON_DIAGNOSTIC_POSITIONS
Definition json.hpp:77
implements the Grisu2 algorithm for binary to decimal floating-point conversion.
Definition json.hpp:17754
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition json.hpp:18201
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.hpp:18037
Target reinterpret_bits(const Source source)
Definition json.hpp:17757
boundaries compute_boundaries(FloatType value)
Definition json.hpp:17898
void grisu2_round(char *buf, int len, std::uint64_t dist, std::uint64_t delta, std::uint64_t rest, std::uint64_t ten_k)
Definition json.hpp:18255
constexpr int kAlpha
Definition json.hpp:18020
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.hpp:18537
constexpr int kGamma
Definition json.hpp:18021
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.hpp:18296
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:18637
JSON_HEDLEY_RETURNS_NON_NULL char * format_buffer(char *buf, int len, int decimal_exponent, int min_exp, int max_exp)
prettify v = buf * 10^decimal_exponent
Definition json.hpp:18689
constexpr bool is_transparent()
Definition json.hpp:4350
constexpr bool is_c_string()
Definition json.hpp:4322
detail namespace with internal helper functions
Definition json.hpp:260
make_integer_sequence< size_t, N > make_index_sequence
Definition json.hpp:3321
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
Definition json.hpp:4425
std::integral_constant< bool,(std::is_signed< OfType >::value &&(sizeof(T)< sizeof(OfType)))||(same_sign< OfType, T >::value &&sizeof(OfType)==sizeof(T)) > never_out_of_range
Definition json.hpp:4232
input_format_t
the supported input formats
Definition json.hpp:6530
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition json.hpp:311
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition json.hpp:6110
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition json.hpp:3649
detector< Default, void, Op, Args... > detected_or
Definition json.hpp:314
decltype(std::declval< T & >().binary(std::declval< Binary & >())) binary_function_t
Definition json.hpp:9738
typename std::conditional< is_usable_as_key_type< typename BasicJsonType::object_comparator_t, typename BasicJsonType::object_t::key_type, KeyTypeCVRef, RequireTransparentComparator, ExcludeObjectKeyType >::value &&!is_json_iterator_of< BasicJsonType, KeyType >::value, std::true_type, std::false_type >::type is_usable_as_basic_json_key_type
Definition json.hpp:4166
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
Definition json.hpp:4446
decltype(std::declval< T & >().end_object()) end_object_function_t
Definition json.hpp:9750
OutStringType concat(Args &&... args)
Definition json.hpp:4505
typename T::value_type value_type_t
Definition json.hpp:3634
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
Definition json.hpp:3352
JSON_HEDLEY_RETURNS_NON_NULL char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition json.hpp:18774
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
Definition json.hpp:9718
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition json.hpp:320
is_detected< string_can_append, StringType, Arg > detect_string_can_append
Definition json.hpp:4428
typename std::enable_if< B, T >::type enable_if_t
Definition json.hpp:3225
parse_event_t
Definition json.hpp:12952
@ value
the parser finished reading a JSON value
Definition json.hpp:12964
@ key
the parser read a key of a value in an object
Definition json.hpp:12962
@ array_end
the parser read ] and finished processing a JSON array
Definition json.hpp:12960
@ array_start
the parser read [ and started to process a JSON array
Definition json.hpp:12958
@ object_start
the parser read { and started to process a JSON object
Definition json.hpp:12954
@ object_end
the parser read } and finished processing a JSON object
Definition json.hpp:12956
std::integral_constant< bool, all_signed< Types... >::value||all_unsigned< Types... >::value > same_sign
Definition json.hpp:4228
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition json.hpp:305
typename std::conditional< is_comparable< Comparator, ObjectKeyType, KeyTypeCVRef >::value &&!(ExcludeObjectKeyType &&std::is_same< KeyType, ObjectKeyType >::value) &&(!RequireTransparentComparator||is_detected< detect_is_transparent, Comparator >::value) &&!is_json_pointer< KeyType >::value, std::true_type, std::false_type >::type is_usable_as_key_type
Definition json.hpp:4148
typename T::pointer pointer_t
Definition json.hpp:3640
std::pair< A1, A2 > from_json_tuple_impl(BasicJsonType &&j, identity_tag< std::pair< A1, A2 > >, priority_tag< 0 >)
Definition json.hpp:5278
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
Definition json.hpp:5083
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition json.hpp:3313
conjunction< std::is_integral< Types >... > all_integral
Definition json.hpp:4218
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.hpp:15736
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition json.hpp:317
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
Definition json.hpp:9746
decltype(std::declval< T & >().null()) null_function_t
Definition json.hpp:9715
void int_to_string(StringType &target, std::size_t value)
Definition json.hpp:5475
T conditional_static_cast(U value)
Definition json.hpp:4206
typename T::difference_type difference_type_t
Definition json.hpp:3637
conjunction< std::is_unsigned< Types >... > all_unsigned
Definition json.hpp:4224
constexpr T static_const< T >::value
Definition json.hpp:3348
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
Definition json.hpp:9742
decltype(std::declval< T & >().number_float( std::declval< Float >(), std::declval< const String & >())) number_float_function_t
Definition json.hpp:9730
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:3101
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
Definition json.hpp:9753
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
Definition json.hpp:4440
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.hpp:5657
typename std::conditional< is_detected< detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType >::value, std::true_type, std::false_type >::type has_erase_with_key_type
Definition json.hpp:4179
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
Definition json.hpp:3728
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
Definition json.hpp:4175
decltype(input_adapter(std::declval< const char * >(), std::declval< const char * >())) contiguous_bytes_input_adapter
Definition json.hpp:6984
bool little_endianness(int num=1) noexcept
determine system byte order
Definition json.hpp:9878
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9865
@ store
store tags as binary type
Definition json.hpp:9868
@ error
throw a parse_error exception in case of a tag
Definition json.hpp:9866
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
Definition json.hpp:3903
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition json.hpp:3329
void concat_into(OutStringType &)
Definition json.hpp:4421
constexpr bool value_in_range_of(T val)
Definition json.hpp:4306
value_t
the JSON type enumeration
Definition json.hpp:3003
@ null
null value
Definition json.hpp:3004
@ number_integer
number value (signed integer)
Definition json.hpp:3009
@ boolean
boolean value
Definition json.hpp:3008
@ discarded
discarded by the parser callback function
Definition json.hpp:3013
@ binary
binary array (ordered collection of bytes)
Definition json.hpp:3012
@ object
object (unordered set of name/value pairs)
Definition json.hpp:3005
@ string
string value
Definition json.hpp:3007
@ number_float
number value (floating-point)
Definition json.hpp:3011
@ number_unsigned
number value (unsigned integer)
Definition json.hpp:3010
@ array
array (ordered collection of values)
Definition json.hpp:3006
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition json.hpp:3652
conjunction< std::is_signed< Types >... > all_signed
Definition json.hpp:4221
constexpr std::size_t unknown_size()
Definition json.hpp:8844
std::array< T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType &&j, identity_tag< std::array< T, sizeof...(Idx)> >, index_sequence< Idx... >)
Definition json.hpp:5166
StringType to_string(std::size_t value)
Definition json.hpp:5483
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.hpp:6370
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
Definition json.hpp:9722
void unescape(StringType &s)
string unescaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3135
typename make_void< Ts... >::type void_t
Definition json.hpp:266
std::size_t combine(std::size_t seed, std::size_t h) noexcept
Definition json.hpp:6352
decltype(std::declval< T & >().parse_error( std::declval< std::size_t >(), std::declval< const std::string & >(), std::declval< const Exception & >())) parse_error_function_t
Definition json.hpp:9760
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:3032
iterator_input_adapter_factory< IteratorType >::adapter_type input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6920
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
Definition json.hpp:3900
typename T::iterator_category iterator_category_t
Definition json.hpp:3646
typename std::conditional< std::is_same< T, void >::value, json_default_base, T >::type json_base_class
Definition json.hpp:14566
is_c_string< uncvref_t< T > > is_c_string_uncvref
Definition json.hpp:4340
error_handler_t
how to treat decoding errors
Definition json.hpp:18854
@ strict
throw a type_error exception in case of invalid UTF-8
Definition json.hpp:18855
@ ignore
ignore invalid UTF-8 sequences
Definition json.hpp:18857
@ replace
replace invalid UTF-8 sequences with U+FFFD
Definition json.hpp:18856
std::size_t concat_length()
Definition json.hpp:4390
std::integral_constant< bool, Value > bool_constant
Definition json.hpp:4312
decltype(input_adapter(std::declval< std::string >())) string_input_adapter_type
Definition json.hpp:6960
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition json.hpp:3211
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
Definition json.hpp:4863
typename T::key_compare detect_key_compare
Definition json.hpp:3712
void to_json(BasicJsonType &j, T b) noexcept
Definition json.hpp:5971
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
Definition json.hpp:4892
integer_sequence< size_t, Ints... > index_sequence
Definition json.hpp:3267
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition json.hpp:323
is_specialization_of<::nlohmann::json_pointer, uncvref_t< T > > is_json_pointer
Definition json.hpp:4129
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
Definition json.hpp:4437
decltype(std::declval< T & >().end_array()) end_array_function_t
Definition json.hpp:9757
std::tuple< Args... > from_json_tuple_impl_base(BasicJsonType &&j, index_sequence< Idx... >)
Definition json.hpp:5266
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
Definition json.hpp:4443
typename T::key_type key_type_t
Definition json.hpp:3631
typename T::reference reference_t
Definition json.hpp:3643
typename T::is_transparent detect_is_transparent
Definition json.hpp:4142
bjdata_version_t
how to encode BJData
Definition json.hpp:15849
is_detected< string_can_append_op, StringType, Arg > detect_string_can_append_op
Definition json.hpp:4434
typename T::mapped_type mapped_type_t
Definition json.hpp:3628
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
Definition json.hpp:4431
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3120
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
Definition json.hpp:9734
decltype(std::declval< T >().template get< U >()) get_template_function
Definition json.hpp:3655
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
Definition json.hpp:9726
std::function< bool(int, parse_event_t, BasicJsonType &)> parser_callback_t
Definition json.hpp:12968
Definition json.hpp:5678
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.hpp:25399
namespace for Niels Lohmann
Definition json.hpp:6181
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
Definition json.hpp:6205
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))
convert a JSON value to any value type
Definition json.hpp:6195
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition json.hpp:6185
typename BasicJsonType::object_t object_t
Definition json.hpp:3721
typename BasicJsonType::default_object_comparator_t object_comparator_t
Definition json.hpp:3722
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
Definition json.hpp:3723
static constexpr int_type eof() noexcept
Definition json.hpp:3781
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3776
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3771
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3752
static constexpr int_type eof() noexcept
Definition json.hpp:3757
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3747
std::false_type value_t
Definition json.hpp:293
Default type
Definition json.hpp:294
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:17791
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition json.hpp:17873
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:17856
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:17779
constexpr diyfp(std::uint64_t f_, int e_) noexcept
Definition json.hpp:17773
static constexpr int kPrecision
Definition json.hpp:17768
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition json.hpp:5880
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition json.hpp:5855
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition json.hpp:5845
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition json.hpp:5867
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition json.hpp:5896
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
Definition json.hpp:5784
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
Definition json.hpp:5793
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition json.hpp:5738
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition json.hpp:5806
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition json.hpp:5832
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition json.hpp:5819
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition json.hpp:5915
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition json.hpp:5936
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition json.hpp:5925
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition json.hpp:5760
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition json.hpp:5771
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition json.hpp:5751
auto operator()(const BasicJsonType &j, T &&val) const noexcept(noexcept(from_json(j, std::forward< T >(val)))) -> decltype(from_json(j, std::forward< T >(val)))
Definition json.hpp:5377
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3674
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3689
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3704
static constexpr std::size_t size() noexcept
Definition json.hpp:3255
an iterator value
Definition json.hpp:13615
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:13619
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:13621
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition json.hpp:13617
static constexpr auto value
Definition json.hpp:3975
ConstructibleStringType laundered_type
Definition json.hpp:3986
static constexpr auto value
Definition json.hpp:3989
static constexpr bool value
Definition json.hpp:3668
typename std::iterator_traits< T >::value_type value_type
Definition json.hpp:6897
static one test(decltype(&C::capacity))
static two test(...)
static constexpr bool value
Definition json.hpp:3896
static constexpr bool value
Definition json.hpp:9779
iterator_input_adapter< iterator_type > adapter_type
Definition json.hpp:6886
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.hpp:6885
static adapter_type create(IteratorType first, IteratorType last)
Definition json.hpp:6888
Default base class of the basic_json class.
Definition json.hpp:14563
nonesuch(nonesuch const &&)=delete
~nonesuch()=delete
void operator=(nonesuch &&)=delete
void operator=(nonesuch const &)=delete
nonesuch(nonesuch const &)=delete
abstract output adapter interface
Definition json.hpp:15722
output_adapter_protocol(const output_adapter_protocol &)=default
virtual ~output_adapter_protocol()=default
virtual void write_character(CharType c)=0
output_adapter_protocol(output_adapter_protocol &&) noexcept=default
virtual void write_characters(const CharType *s, std::size_t length)=0
struct to capture the start position of the current token
Definition json.hpp:3166
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3170
std::size_t lines_read
the number of lines read
Definition json.hpp:3172
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3168
static JSON_INLINE_VARIABLE constexpr T value
Definition json.hpp:3343
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition json.hpp:6150
integer_sequence< T, Ints...,(Ints+SeqSize)..., 2 *SeqSize > type
Definition json.hpp:3285
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition json.hpp:3293
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:6771
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:6713
SAX interface
Definition json.hpp:8729
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
json_sax()=default
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:8730
typename BasicJsonType::string_t string_t
Definition json.hpp:8733
virtual bool end_array()=0
the end of an array was read
json_sax(const json_sax &)=default
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:8732
virtual bool null()=0
a null value was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:8731
json_sax(json_sax &&) noexcept=default
typename BasicJsonType::binary_t binary_t
Definition json.hpp:8734
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition json.hpp:19836
std::vector< std::pair< const Key, T >, Allocator > Container
Definition json.hpp:19839
std::pair< iterator, bool > insert(value_type &&value)
Definition json.hpp:20130
typename Container::value_type value_type
Definition json.hpp:19843
std::equal_to< Key > key_compare
Definition json.hpp:19847
iterator erase(iterator pos)
Definition json.hpp:20008
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
Definition json.hpp:19853
T & operator[](KeyType &&key)
Definition json.hpp:19895
typename Container::iterator iterator
Definition json.hpp:19840
const T & at(KeyType &&key) const
Definition json.hpp:19955
T & at(KeyType &&key)
Definition json.hpp:19927
const T & operator[](KeyType &&key) const
Definition json.hpp:19907
iterator find(const key_type &key)
Definition json.hpp:20092
iterator erase(iterator first, iterator last)
Definition json.hpp:20013
const T & at(const key_type &key) const
Definition json.hpp:19940
const_iterator find(const key_type &key) const
Definition json.hpp:20118
T & operator[](const key_type &key)
Definition json.hpp:19888
size_type erase(KeyType &&key)
Definition json.hpp:19989
typename Container::size_type size_type
Definition json.hpp:19842
ordered_map() noexcept(noexcept(Container()))
Definition json.hpp:19852
void insert(InputIt first, InputIt last)
Definition json.hpp:20153
size_type count(const key_type &key) const
Definition json.hpp:20066
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
Definition json.hpp:19875
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
Definition json.hpp:20149
size_type erase(const key_type &key)
Definition json.hpp:19968
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
Definition json.hpp:19857
std::pair< iterator, bool > insert(const value_type &value)
Definition json.hpp:20135
size_type count(KeyType &&key) const
Definition json.hpp:20080
ordered_map(It first, It last, const Allocator &alloc=Allocator())
Definition json.hpp:19855
const T & operator[](const key_type &key) const
Definition json.hpp:19900
iterator find(KeyType &&key)
Definition json.hpp:20106
T & at(const key_type &key)
Definition json.hpp:19912
typename Container::const_iterator const_iterator
Definition json.hpp:19841
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
Definition json.hpp:19860
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
Definition json.hpp:25368
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:25382